Recommandations d'apprentissage gratuites associées : Tutoriel de base Java
Classes auxiliaires couramment utilisées
Description du problème : Supposons qu'il y ait 7 étudiants qui étudient le soir. Le moniteur a la clé et est responsable du verrouillage de la porte. Le moniteur doit attendre que tout le monde soit parti avant de pouvoir éteindre les lumières et verrouiller la porte. L’ordre de ces six étudiants n’est pas ordonné, et je ne sais pas quand ils sont partis. Chacun des six étudiants a suivi ses propres cours d'auto-apprentissage, sans aucune interaction entre les deux. Si les 6 étudiants sont des threads ordinaires et que le moniteur est le thread principal, comment pouvons-nous faire en sorte que le thread principal attende qu'un groupe de threads termine son exécution avant que le thread principal puisse terminer son exécution ? public class CountDownLatchDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=1;i{
System.out.println(Thread.currentThread().getName()+"\t离开教室");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+"\t班长关门走人");
}}
Enfin, il y a trois personnes enfermées dans le professeur. Cela peut provoquer des accidents, donc ce n'est certainement pas possible.
Si nous voulons obtenir cet effet, nous devons attendre que tous les autres threads aient fini de s'exécuter avant que le thread principal puisse s'exécuter. Vous devez utiliser la classe CountDownLatch dans JUC1.2 Introduction à la classe CountDownLatch :
CountDownLatch est une classe d'outils de synchronisation utilisée pour coordonner la synchronisation entre plusieurs threads, ou la communication entre les threads (plutôt que de servir d'exclusion mutuelle).
CountDownLatch permet à un thread d'attendre que d'autres threads terminent leur travail avant de continuer à s'exécuter . Utilisez un compteur pour mettre en œuvre. La valeur initiale du compteur est le nombre de threads. Lorsque chaque thread termine sa tâche, la valeur du compteur sera décrémentée de un. Lorsque la valeur du compteur est 0, cela signifie que tous les threads ont terminé certaines tâches, puis les threads en attente sur CountDownLatch peuvent reprendre l'exécution des tâches suivantes
.Description de CountDownLatch : décompte, décompte, démarrage du loquet
1.2.3 Utilisation de CountDownLatchUn certain fil démarre Attendez pour que n threads terminent l'exécution avant de s'exécuter. Initialisez le compteur CountDownLatch à new CountDownLatch(n). Chaque fois qu'un thread de tâche termine son exécution, le compteur est décrémenté de 1 countdownLatch.countDown() Lorsque la valeur du compteur devient 0, le thread wait() sur CountDownLatch sera réveillé. Un scénario d'application typique est que lors du démarrage d'un service, le thread principal doit attendre que plusieurs composants soient chargés avant de poursuivre l'exécution.
Code source du constructeur sous-jacent de CountDownLatch
public CountDownLatch(int count) { if (count <p><strong>1.3.Cas CountDownLatch : </strong></p><pre class="brush:php;toolbar:false">public static void main(String[] args) throws InterruptedException { //6个同学正在上自习,每个人就有一个1计数器,走1个数字减1,main线程启动,必须要等计时器从6变成0,才能开始。 CountDownLatch countDownLatch=new CountDownLatch(6); for(int i=1;i{ System.out.println(Thread.currentThread().getName()+"\t离开教室"); countDownLatch.countDown(); //计算减少一个 },String.valueOf(i)).start(); } countDownLatch.await(); //班长前面需要被阻塞 System.out.println(Thread.currentThread().getName()+"\t班长关门走人"); }
Capture d'écran des résultats en cours d'exécution
Ici Nous ne savons pas quand tout le monde partira, mais nous pouvons garantir que le chef d'équipe sera le dernier à partir à chaque fois.
1.4.Résumé des principes
CountDownLatch a principalement deux méthodes Lorsqu'un ou plusieurs threads appellent la méthode wait, ces threads seront bloqués. L'appel de la méthode countDown par d'autres threads décrémentera le compteur de 1 (le thread appelant la méthode countDown ne sera pas bloqué)
Lorsque la valeur du compteur devient 0, le thread bloqué par la méthode wait sera réveillé et exécuté continuera.
2. CyclicBarrier
2.1. Introduction à CyclicBarrier
Du sens littéral, le sens chinois de cette classe est « clôture circulante ». Cela signifie en gros une barrière recyclable. Sa fonction est de faire attendre que tous les threads soient terminés avant de passer à l'étape suivante.
L'exemple ci-dessus du chef d'équipe fermant la porte fait un compte à rebours, ici c'est l'inverse, faisant une addition, en commençant lorsque le nombre est atteint. Par exemple, lorsque tout le monde est là, recommencez la réunion.
par exemple, tout comme dans la vie, nous inviterons des collègues à aller à une réunion. Certains collègues peuvent arriver en avance et certains collègues peuvent arriver en retard, mais cette réunion stipule qu'il faut attendre que tout le monde soit arrivé avant de pouvoir officiellement. Ayez une réunion. Les collègues ici sont le fil conducteur, et la réunion est la CyclicBarrier.
Méthode constructeur
public CyclicBarrier(int parties)public CyclicBarrier(int parties, Runnable barrierAction)
2.2. Cas : Récupérez 7 boules de dragon pour invoquer le dragon 截图 3.Semophore 3.1.Semophore简介 前面讨论的问题都是多对一的问题,我们现在可以讨论多对多的问题了。 假设有7个兄弟开车上班,而现在只有4个车位。7部车并列开进4个车位,每个车停了多长时间未知,资源被占用完了。假设有一个车只停了2s,那么它走了,外面的车又可以进来了。走一个进一个,最后全部都可以进去。而semophore就是控制多线程的并发策略。 简单理解来说,Semaphore:信号量主要用于两个目的:一个是用于多个共享资源的互斥使用;另一个用于并发线程数量的控制。 Semaphore类有两个重要方法 1、semaphore.acquire(); 2、semaphore.release(); 3.2.抢车位问题 运行结果截图: 3.3.原理总结 在信号量上我们定义两种操作: acquire(获取)当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等待下去,直到有线程释放信号量,或超时。 release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。 信号量主要用于两个目的:一个是用于多个共享资源的互斥使用;另一个用于并发线程数量的控制 如果把资源数从3变成1了,此时就等价于synchronized。public static void main(String[] args) {
// TODO Auto-generated method stub
CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{System.out.println("召唤神龙");});
for(int i=1;i{
System.out.println(Thread.currentThread().getName()+"\t收集到第"+tempInt+"颗龙珠");
try {
//某个线程收集到了龙珠只能先等着,等龙珠收齐了才能召唤神龙
cyclicBarrier.await();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
},String.valueOf(i)).start();;
}
}
请求一个信号量,这时候信号量个数-1,当减少到0的时候,下一次acquire不会再执行,只有当执行一个release()的时候,信号量不为0的时候才可以继续执行acquire
释放一个信号量,这时候信号量个数+1,public static void main(String[] args) {
//模拟6部车抢3个空车位
Semaphore semaphore=new Semaphore(3);//模拟资源类,有3个空车位
for(int i=1;i{
try {
//谁先抢到了,谁就占一个车位,并且要把semaphore中的资源数减1
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"\t抢占到了车位");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"\t离开了车位");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//释放车位
semaphore.release();
}
},String.valueOf(i)).start();
}
}
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!