Ce résumé résume ma compréhension des méthodes de communication entre les threads dans le multi-threading JAVA. Je discute principalement de la communication entre les threads via du code combiné avec du texte. Par conséquent, j'ai extrait quelques exemples de codes du livre.
①Synchronisation
La synchronisation mentionnée ici fait référence à la communication entre plusieurs threads via le mot-clé synchronisé.
Exemple de référence :
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(); } }
Puisque le thread A et le thread B contiennent le même objet de la classe MyObject, bien que les deux threads doivent appeler des méthodes différentes, ils sont exécutés de manière synchrone. Par exemple : Le thread B doit attendre que le thread A ait fini d'exécuter la méthode methodA() avant de pouvoir exécuter la méthode methodB(). De cette façon, le thread A et le thread B établissent la communication.
Cette méthode est essentiellement une communication à « mémoire partagée ». Plusieurs threads doivent accéder à la même variable partagée. Celui qui obtient le verrou (obtient l'autorisation d'accès) peut l'exécuter.
②while méthode d'interrogation
Le code est le suivant :
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(); } }
De cette façon, le thread A modifie continuellement les conditions et le thread ThreadB continue de transmettre l'instruction while Check si cette condition (list.size()==5) est vraie, réalisant ainsi la communication entre les threads. Mais cette méthode gaspillera les ressources du processeur. La raison pour laquelle il s'agit d'un gaspillage de ressources est que lorsque le planificateur JVM confie le processeur au thread B pour exécution, il n'effectue aucun travail "utile". Il teste simplement en permanence si une certaine condition est vraie. C'est similaire à la façon dont dans la vraie vie, une personne continue de regarder l'écran du téléphone pour voir si un appel arrive, au lieu de : faire autre chose. Lorsqu'un appel arrive, le téléphone sonne pour l'avertir que l'appel arrive.
③Mécanisme d'attente/notification
Le code est le suivant :
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(); } } }
Le thread A doit attendre qu'une certaine condition soit remplie (list.size()= =5) avant d'exécuter l'opération. Le fil B ajoute des éléments à la liste et modifie la taille de la liste.
Comment A et B communiquent-ils ? En d’autres termes, comment le thread A sait-il que list.size() vaut déjà 5 ?
Les méthodes wait() et notify() de la classe Object sont utilisées ici.
Lorsque la condition n'est pas remplie (list.size() !=5), le thread A appelle wait() pour abandonner le CPU et entrer dans l'état de blocage. ---Il n'occupe pas le CPU comme ②pendant l'interrogation
Lorsque les conditions sont remplies, le thread B appelle notify() pour notifier le thread A. Le soi-disant thread de notification A consiste à réveiller le thread A et à laisser il entre dans l'état exécutable.
L'un des avantages de cette méthode est que le taux d'utilisation du processeur est amélioré.
Mais il y a aussi quelques défauts : par exemple, le thread B s'exécute en premier, ajoute 5 éléments à la fois et appelle notify() pour envoyer une notification, alors que le thread A est toujours en cours d'exécution à ce moment-là ; et appelle wait(), alors il ne pourra jamais être réveillé. Parce que le fil B a déjà envoyé une notification et n'enverra plus de notifications à l'avenir. Cela montre qu'une notification trop précoce perturbera la logique d'exécution du programme.
Ce qui précède représente l'intégralité du contenu de cet article, j'espère qu'il sera utile à tous ceux qui apprennent la programmation Java.
Pour des explications plus détaillées sur les méthodes de communication entre les threads Java, veuillez faire attention au site Web PHP chinois !