1. Einleitung
Diese Zusammenfassung fasst mein Verständnis der Kommunikationsmethoden zwischen Threads im JAVA-Multithreading zusammen. Ich diskutiere hauptsächlich die Kommunikation zwischen Threads mithilfe von Code in Kombination mit Text, daher habe ich einige aus dem Buch entnommen. Beispielcode.
2. Kommunikationsmethoden zwischen Threads
① Synchronisation
Die hier erwähnte Synchronisation bezieht sich auf die Kommunikation zwischen mehreren Threads über das synchronisierte Schlüsselwort.
Referenzbeispiel:
public class MyObject { synchronized public void methodA() { //do something.... } synchronized public void methodB() { //do some other thing } } public class ThreadA extends Thread { private MyObject object; //省略构造方法 @Override public void run() { super.run(); object.methodA(); } } public class ThreadB extends Thread { private MyObject object; //省略构造方法 @Override public void run() { super.run(); object.methodB(); } } public class Run { public static void main(String[] args) { MyObject object = new MyObject(); //线程A与线程B 持有的是同一个对象:object ThreadA a = new ThreadA(object); ThreadB b = new ThreadB(object); a.start(); b.start(); } }
Da Thread A und Thread B dasselbe Objekt der MyObject-Klasse enthalten, werden die beiden Threads synchron ausgeführt, obwohl sie unterschiedliche Methoden aufrufen müssen. Beispiel: Thread B muss warten, bis Thread A die Ausführung der Methode methodA() abgeschlossen hat, bevor er die Methode methodB() ausführen kann. Auf diese Weise erreichen Thread A und Thread B eine Kommunikation.
Bei dieser Methode handelt es sich im Wesentlichen um „Shared Memory“-Kommunikation. Mehrere Threads müssen auf dieselbe gemeinsam genutzte Variable zugreifen. Wer die Sperre erhält (Zugriffsberechtigung erhält), kann sie ausführen.
②while-Abfragemethode
Der Code lautet wie folgt:
import java.util.ArrayList; import java.util.List; public class MyList { private List<String> list = new ArrayList<String>(); public void add() { list.add("elements"); } public int size() { return list.size(); } } import mylist.MyList; public class ThreadA extends Thread { private MyList list; public ThreadA(MyList list) { super(); this.list = list; } @Override public void run() { try { for (int i = 0; i < 10; i++) { list.add(); System.out.println("添加了" + (i + 1) + "个元素"); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } } import mylist.MyList; public class ThreadB extends Thread { private MyList list; public ThreadB(MyList list) { super(); this.list = list; } @Override public void run() { try { while (true) { if (list.size() == 5) { System.out.println("==5, 线程b准备退出了"); throw new InterruptedException(); } } } catch (InterruptedException e) { e.printStackTrace(); } } } import mylist.MyList; import extthread.ThreadA; import extthread.ThreadB; public class Test { public static void main(String[] args) { MyList service = new MyList(); ThreadA a = new ThreadA(service); a.setName("A"); a.start(); ThreadB b = new ThreadB(service); b.setName("B"); b.start(); } }
Auf diese Weise ändert Thread A kontinuierlich die Bedingungen und Thread ThreadB übergibt weiterhin die while-Anweisung ob diese Bedingung (list.size()==5) wahr ist, wodurch die Kommunikation zwischen Threads realisiert wird. Diese Methode verschwendet jedoch CPU-Ressourcen. Der Grund dafür, dass es sich um eine Verschwendung von Ressourcen handelt, liegt darin, dass der JVM-Scheduler, wenn er die CPU zur Ausführung an Thread B übergibt, keine „nützliche“ Arbeit ausführt, sondern lediglich ständig prüft, ob eine bestimmte Bedingung erfüllt ist. Es ist ähnlich wie im wirklichen Leben, wenn eine Person ständig auf den Telefonbildschirm schaut, um zu sehen, ob ein Anruf eingeht, anstatt: Wenn ein Anruf eingeht, klingelt das Telefon, um sie darüber zu informieren.
③Warte-/Benachrichtigungsmechanismus
Der Code lautet wie folgt:
import java.util.ArrayList; import java.util.List; public class MyList { private static List<String> list = new ArrayList<String>(); public static void add() { list.add("anyString"); } public static int size() { return list.size(); } } public class ThreadA extends Thread { private Object lock; public ThreadA(Object lock) { super(); this.lock = lock; } @Override public void run() { try { synchronized (lock) { if (MyList.size() != 5) { System.out.println("wait begin " + System.currentTimeMillis()); lock.wait(); System.out.println("wait end " + System.currentTimeMillis()); } } } catch (InterruptedException e) { e.printStackTrace(); } } } public class ThreadB extends Thread { private Object lock; public ThreadB(Object lock) { super(); this.lock = lock; } @Override public void run() { try { synchronized (lock) { for (int i = 0; i < 10; i++) { MyList.add(); if (MyList.size() == 5) { lock.notify(); System.out.println("已经发出了通知"); } System.out.println("添加了" + (i + 1) + "个元素!"); Thread.sleep(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } } public class Run { public static void main(String[] args) { try { Object lock = new Object(); ThreadA a = new ThreadA(lock); a.start(); Thread.sleep(50); ThreadB b = new ThreadB(lock); b.start(); } catch (InterruptedException e) { e.printStackTrace(); } } }
Thread A muss warten, bis eine bestimmte Bedingung erfüllt ist (list.size()= =5), bevor Sie den Vorgang ausführen. Thread B fügt der Liste Elemente hinzu und ändert die Größe der Liste.
Wie kommunizieren A und B? Mit anderen Worten: Woher weiß Thread A, dass list.size() bereits 5 ist?
Hier werden die Methoden wait() und notify() der Object-Klasse verwendet.
Wenn die Bedingung nicht erfüllt ist (list.size() !=5), ruft Thread A wait() auf, um die CPU aufzugeben und in den Blockierungszustand zu wechseln. ---Es belegt die CPU nicht wie ②während der Abfrage
Wenn die Bedingungen erfüllt sind, ruft Thread B notify() auf, um Thread A zu benachrichtigen. Der sogenannte benachrichtigende Thread A soll Thread A aufwecken und loslassen Es wechselt in den lauffähigen Zustand.
Ein Vorteil dieser Methode besteht darin, dass die CPU-Auslastung verbessert wird.
Aber es gibt auch einige Mängel: Beispielsweise wird Thread B zuerst ausgeführt, fügt 5 Elemente auf einmal hinzu und ruft notify() auf, um eine Benachrichtigung zu senden, während Thread A zu diesem Zeitpunkt noch ausgeführt wird, wenn Thread A ausgeführt wird und ruft wait() auf, dann kann es nie geweckt werden. Weil Thread B bereits eine Benachrichtigung gesendet hat und in Zukunft keine Benachrichtigungen mehr senden wird. Dies zeigt, dass eine zu frühe Benachrichtigung die Ausführungslogik des Programms stört.
Der obige Artikel bietet ein detailliertes Verständnis der Kommunikationsmethoden zwischen Threads im JAVA-Multithreading. Dies ist der gesamte vom Herausgeber geteilte Inhalt. Ich hoffe, er kann Ihnen eine Referenz geben wird die chinesische PHP-Website unterstützen.
Für ein tieferes Verständnis der Kommunikationsmethoden zwischen JAVA-Multithreads und verwandten Artikeln achten Sie bitte auf die chinesische PHP-Website!