Maison > Java > javaDidacticiel > Quels sont les moyens par lesquels les threads Java coopèrent ?

Quels sont les moyens par lesquels les threads Java coopèrent ?

王林
Libérer: 2023-05-17 20:34:15
avant
1500 Les gens l'ont consulté

Pourquoi les threads doivent-ils coopérer ?

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.

Introduction

Les deux méthodes les plus courantes de collaboration entre threads en Java : utiliser Object.wait(), Object.notify() et utiliser Condition

Méthode 1

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()+"释放了锁");
            }
        }
    }
    Copier après la connexion
  • Résultats d'exécution

Thread Thread-1 appelé object.notify()

Thread Thread-1 libère le verrou

Thread Thread-0 acquiert le verrou


Méthode 2

La condition n'est apparue que dans Java 1.5. Elle est utilisée pour remplacer les fonctions wait() et notify() des objets traditionnels. Pour réaliser une collaboration entre les threads, par rapport à l'utilisation des fonctions wait() et notify() de l'objet, il est plus sûr et plus efficace de utilisez les méthodes wait() et signal() de Condition1 pour réaliser une collaboration entre les threads

  • 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();
                    }
                }
            }
        }
    }
    Copier après la connexion

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!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal