当前位置:网站首页>4 ans d'expérience de travail, 5 modes de communication Multi - thread ne peuvent pas être décrits, vous osez croire?

4 ans d'expérience de travail, 5 modes de communication Multi - thread ne peuvent pas être décrits, vous osez croire?

2022-06-25 01:08:00 Java confident

Cliquez sur le numéro public,Article technique pratiqueSoyez au courant1314cac049ec0b34f1704bd3d278c229.png

Questions

Il y a deux fils,A Les Threads ajoutent des éléments à une collection à tour de rôle“abc”String,Dix ajouts au total,Quand ajouté à la cinquième fois,L'espoir B Le thread peut recevoir A Notification du thread,Et puis B Le thread effectue les opérations commerciales connexes.Il existe deux modèles de communication entre les fils:Mémoire partagée et messagerie,Les deux modèles de base sont mis en œuvre de la manière suivante.

Un.、Utiliser volatile Mots clés

Basé sur volatile Le mot - clé pour permettre la communication entre les fils est l'idée d'utiliser la mémoire partagée.Cela signifie que plusieurs Threads écoutent simultanément une variable,Quand cette variable change ,Le thread est capable de percevoir et d'exécuter l'entreprise correspondante.C'est aussi la façon la plus simple de le faire

public class TestSync {
    //Définir des variables partagées pour la communication,Il a besoinvolatileModification,Sinon, le thread n'est pas à jour
    static volatile boolean notice = false;

    public static void main(String[] args) {
        List<String>  list = new ArrayList<>();
        //ThreadA
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("ThreadAAjouter un élément,En ce momentlistDesizePour:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    notice = true;
            }
        });
        //ThreadB
        Thread threadB = new Thread(() -> {
            while (true) {
                if (notice) {
                    System.out.println("ThreadBNotification reçue,Commencez votre propre entreprise...");
                    break;
                }
            }
        });
        //Il faut d'abord démarrer le threadB
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // Redémarrer le threadA
        threadA.start();
    }
}

2.、Utiliser Object Classe wait()/notify()

Object La classe fournit un moyen de communiquer entre les fils:wait()notify()notifyAll(),Ils sont la base de la communication multithreadée,Et l'idée de cette mise en œuvre est naturellement la communication entre les fils.

Attention!:wait/notify Doit coopérer synchronized Utiliser,wait Méthode de déverrouillage,notify La méthode ne libère pas la serrure.wait C'est à l'intérieur d'un fil qui est entré dans la serrure de synchronisation,Laissez - vous libérer temporairement la serrure de synchronisation,Afin que les autres fils qui attendent cette serrure puissent obtenir la serrure de synchronisation et l'exécuter,Seul un autre thread a appelénotify(),notifyNe pas libérer la serrure,J'ai juste dit que j'avais appelé.wait() Le thread peut participer à la compétition pour obtenir la serrure ,Mais pas tout de suite.,Parce que la serrure est toujours entre les mains de quelqu'un d'autre.,Quelqu'un d'autre n'a pas encore été libéré.,Appelez wait() Un ou plusieurs fils de wait Statut, Participer de nouveau au verrouillage de l'objet concurrent , Si le programme peut être verrouillé à nouveau , Pour continuer à descendre .

public class TestSync {
    public static void main(String[] args) {
        //Définir un objet de verrouillage
        Object lock = new Object();
        List<String>  list = new ArrayList<>();
        // ThreadA
        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("ThreadAAjouter un élément,En ce momentlistDesizePour:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        lock.notify();//Réveillez - vous.BThread
                }
            }
        });
        //ThreadB
        Thread threadB = new Thread(() -> {
            while (true) {
                synchronized (lock) {
                    if (list.size() != 5) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("ThreadBNotification reçue,Commencez votre propre entreprise...");
                }
            }
        });
        //Il faut d'abord démarrer le threadB
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Redémarrer le threadA
        threadA.start();
    }
}

Résultat de la sortie ,Dans le thread A Envoyer notify() Après la notification de réveil,C'est quand même après avoir terminé le travail de mon propre fil,Thread B Pour commencer l'exécution, Exactement. notify() Pas de déverrouillage,Et wait() Relâchez la serrure..

Trois、UtiliserJUCClasse d'outils CountDownLatch

jdk1.5 Aprèsjava.util.concurrent De nombreuses classes d'outils liées à la programmation simultanée sont disponibles sous le paquet , Simplifie l'écriture de codes de programmation simultanés ,CountDownLatch Basé sur AQS Cadre, Cela équivaut à maintenir une variable partagée entre les Threads state.

public class TestSync {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        List<String>  list = new ArrayList<>();
        //ThreadA
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("ThreadAAjouter un élément,En ce momentlistDesizePour:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    countDownLatch.countDown();
            }
        });
        //ThreadB
        Thread threadB = new Thread(() -> {
            while (true) {
                if (list.size() != 5) {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("ThreadBNotification reçue,Commencez votre propre entreprise...");
                break;
            }
        });
        //Il faut d'abord démarrer le threadB
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Redémarrer le threadA
        threadA.start();
    }
}

Quatre、Utiliser ReentrantLock Union Condition

public class TestSync {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();

        List<String> list = new ArrayList<>();
        //ThreadA
        Thread threadA = new Thread(() -> {
            lock.lock();
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("ThreadAAjouter un élément,En ce momentlistDesizePour:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    condition.signal();
            }
            lock.unlock();
        });
        //ThreadB
        Thread threadB = new Thread(() -> {
            lock.lock();
            if (list.size() != 5) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("ThreadBNotification reçue,Commencez votre propre entreprise...");
            lock.unlock();
        });
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadA.start();
    }
}

Ce n'est pas très bien utilisé , Codage complexe ,Et les fils B Par A Impossible d'exécuter immédiatement après le réveil parce qu'il n'y a pas de serrure acquise ,C'est - à - dire,A Après l'opération de réveil ,Ne pas libérer la serrure. C'est comme ça que Object De wait()/notify() C'est pareil.

Cinq、Basic LockSupport .Réaliser le blocage et le réveil entre les fils

LockSupport Est un outil très flexible pour réaliser le blocage et le réveil entre les fils, Utilisez - le sans vous soucier d'attendre que le thread fonctionne en premier ou de réveiller le thread à fonctionner en premier , Mais il faut connaître le nom du fil .

public class TestSync {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        //ThreadB
        final Thread threadB = new Thread(() -> {
            if (list.size() != 5) {
                LockSupport.park();
            }
            System.out.println("ThreadBNotification reçue,Commencez votre propre entreprise...");
        });
        //ThreadA
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("ThreadAAjouter un élément,En ce momentlistDesizePour:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    LockSupport.unpark(threadB);
            }
        });
        threadA.start();
        threadB.start();
    }
}

Source::blog.csdn.net/ChineseSoftware/article/

details/118390388

Recommandations

JavaUn dictionnaire de questions d'entrevue

Groupe de volume interne technique,Venez étudier ensemble.!!

e92e3dff67b1cf09d6b4b8d25432ca07.png

PS:Parce que la plate - forme des numéros publics a changé les règles de poussée,Si vous ne voulez pas manquer le contenu,N'oubliez pas de lire un peu“Je regarde”,Ajouter“Étoile”,De cette façon, chaque fois qu'un nouvel article est poussé, il apparaîtra pour la première fois dans votre liste d'abonnements.Point“Je regarde”Soutenez - nous!

原网站

版权声明
本文为[Java confident]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/176/202206242024070725.html