Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung der Kommunikationsmethoden zwischen Java-Threads

Detaillierte Erläuterung der Kommunikationsmethoden zwischen Java-Threads

高洛峰
高洛峰Original
2017-01-05 14:35:221683Durchsuche

Diese Zusammenfassung fasst mein Verständnis der Kommunikationsmethoden zwischen Threads im JAVA-Multithreading zusammen. Ich bespreche hauptsächlich die Kommunikation zwischen Threads durch Code in Kombination mit Text. Der spezifische Inhalt ist wie folgt

①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 testet, 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 Klasse Object 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; 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.

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für alle hilfreich sein, die Java-Programmierung lernen.

Ausführlichere Erläuterungen zu den Kommunikationsmethoden zwischen Java-Threads finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn