Les threads coopèrent les uns avec les autres pour effectuer un certain travail. Par exemple : un thread modifie la valeur d'un objet, et un autre thread détecte le changement et effectue ensuite l'opération correspondante. avec un thread, et l'exécution finale est un autre thread. Grâce à ce modèle, les producteurs et les consommateurs sont séparés, réalisant ainsi l'isolement du « Quoi » et du « Comment ». Le moyen le plus simple consiste à laisser le thread consommateur effectuer une boucle continue pour vérifier si les variables répondent aux attentes, définir des conditions non satisfaites dans la boucle while et quitter la boucle while si les conditions sont remplies, complétant ainsi le travail du consommateur. Il y a deux problèmes avec ce type de collaboration entre les fils de discussion :
(1) Il est difficile de garantir la ponctualité.
(2) Difficile de réduire les frais généraux. Si le temps de veille est réduit, par exemple pendant 1 milliseconde, les consommateurs peuvent détecter les changements de conditions plus rapidement, mais cela peut consommer plus de ressources processeur, entraînant un gaspillage inutile.
Les deux méthodes les plus courantes de collaboration entre threads en Java : utiliser Object.wait(), Object.notify() et utiliser Condition
Les méthodes wait, notify et notifyAll dans Object sont définies comme follow
public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException; méthodes locales, et c'est une méthode finale et ne peut pas être remplacée
Appelez la méthode wait() d'un objet pour bloquer le thread actuel, et le thread actuel doit posséder le moniteur (c'est-à-dire le verrou) de cet objet
Appeler un objet La méthode notify() peut réveiller un thread qui attend le moniteur de cet objet. S'il y a plusieurs threads qui attendent le moniteur de cet objet, un seul des threads peut être réveillé
. L'appel de la méthode notifyAll() peut réveiller tous les threads qui attendent le moniteur de cet objet. Le thread en attente du moniteur de cet objet
La raison pour laquelle ces trois méthodes sont déclarées dans la classe Object est que chacune d'elles est déclarée. l'objet a un moniteur (c'est-à-dire un verrou)
Appelez la méthode wait() d'un objet, le thread actuel Vous devez posséder le moniteur (c'est-à-dire un verrou) de cet objet, donc l'appel de la méthode wait() doit être effectué dans un bloc synchronisé ou méthode synchronisée
Exemple
public class Test { public static Object object = new Object(); public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } thread2.start(); } static class Thread1 extends Thread{ @Override public void run() { synchronized (object) { try { object.wait(); } catch (InterruptedException e) { } System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁"); } } } static class Thread2 extends Thread{ @Override public void run() { synchronized (object) { object.notify(); System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()"); } System.out.println("线程"+Thread.currentThread().getName()+"释放了锁"); } } }
Thread Thread-1 libère le verrou
Thread Thread-0 acquiert le verrou
Méthode 2
La condition est une interface, essentiellement les méthodes sont les méthodes wait() et signal()
La condition dépend de l'interface Lock. Le code de base à utiliser. générer une Condition est lock.newCondition()
Appelez les méthodes wait() et signal() de Condition, qui sont toutes deux requises dans la protection du verrouillage, c'est-à-dire qu'elle doit être utilisée entre lock.lock() et lock.unlock
Exemple
public class Test { private int queueSize = 10; private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize); private Lock lock = new ReentrantLock(); private Condition notFull = lock.newCondition(); private Condition notEmpty = lock.newCondition(); public static void main(String[] args) { Test test = new Test(); Producer producer = test.new Producer(); Consumer consumer = test.new Consumer(); producer.start(); consumer.start(); } class Consumer extends Thread{ @Override public void run() { consume(); } private void consume() { while(true){ lock.lock(); try { while(queue.size() == 0){ try { System.out.println("队列空,等待数据"); notEmpty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.poll(); //每次移走队首元素 notFull.signal(); System.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素"); } finally{ lock.unlock(); } } } } class Producer extends Thread{ @Override public void run() { produce(); } private void produce() { while(true){ lock.lock(); try { while(queue.size() == queueSize){ try { System.out.println("队列满,等待有空余空间"); notFull.await(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.offer(1); //每次插入一个元素 notEmpty.signal(); System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size())); } finally{ lock.unlock(); } } } } }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!