CountDownLatch
est une classe d'outils de synchronisation multi-thread. Dans un environnement multi-thread, elle permet à plusieurs threads d'attendre la fin de l'exécution du thread précédent. À en juger par le nom de la classe, CountDown
signifie décrémenter le nombre, nous pouvons donc le comprendre comme un compteur. CountDownLatch
是一个多线程同步工具类,在多线程环境中它允许多个线程处于等待状态,直到前面的线程执行结束。从类名上看CountDown
既是数量递减的意思,我们可以把它理解为计数器。
countDown()
:计数器递减方法。
await()
:使调用此方法的线程进入等待状态,直到计数器计数为0时主线程才会被唤醒。
await(long, TimeUnit)
:在await()
方法的基础上增加了超时策略,若等待超时仍未有结果则会直接唤醒主线程运行。
在这里我们用一段简单的代码进行演示:
@Slf4j public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); new Thread(() -> { log.info("hello this is thread one"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread two"); countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread three"); countDownLatch.countDown(); }).start(); countDownLatch.await(); log.info("say good bye!"); } }
由上面的代码可见,我们创建了一个CountDownLatch
计数器为3和三个线程同步运行。在main主线程中调用了countDownLatch.await()
方法使主线程进入阻塞。其中三个线程任务执行完毕后都会调用countDownLatch.countDown()
方法对计数器进行递减,当三个线程任务都执行完毕后计数器计数值为0时主线程被唤醒。
注:在创建
CountDownLatch
实例时必须定义计数器值,一般相对较合理的用法是该值的定义需要经过合理的计算使计数值与需要并行的线程数相等,在每个线程执行完成后做计数递减,最终唤醒主线程继续执行。
CountDownLatch
计数值设置大于线程数,那么最终所有线程都执行完了,而计数为递减到0那么主线程将会一直处于等待状态。
CountDownLatch
计数值设置小于并发线程数,那么可能在部分线程未执行完毕时,计数就已经递减到0,则主线程会被提前唤醒。
如下图,主线程阻塞与唤醒的核心就是计数器,只有当所有线程执行完成计数逐个递减最终才会唤起await()
阻塞中的主线程。
注:
await()
可以阻塞一个线程,也可以阻塞多个线程,如果是阻塞多个线程,那么在计数为0时将会唤醒所有被阻塞的线程。
在简单了解完CountDownLatch
的作用后,相信各位最终目的还是想了解如何去使用,在哪些场景下使用更加合适,接下来我就拿一个对账业务的场景详细分析一下。
在当前的情况下,许多平台会与银联、微信、支付宝等支付渠道对接交易,因此无法避免进行对账。对账通常都会在每日的凌晨去处理,一方面是凌晨时间点多数平台访问量都会较小,服务器压力也比较轻松,而且此时出账也比较合理,所以在这个时间点做对账也是一个大数据量计算的操作。
上面讲这么多好像都没说到重点,在处理对账之前首先我们肯定是需要通过各个支付渠道获取对账单文件,那么该如何操作呢?
对账文件下载(第一阶段):在这种情况下可以设计三个任务并发去获取对账文件,使用CountDownLatch
阻塞主线程,等待三个任务都获取到文件的时候做计数递减,最终唤醒主线将标记本阶段处理完成,并发起进入下一阶段的通知。
对账文件解析(第二阶段):在上个阶段已下载完成的文件文件中,此阶段要做的就是解析文件。由于三个渠道都是不同的厂家那么文件的内容格式肯定都是不一样的,这时候我们又可以使用CountDownLatch
countDown()
: Méthode de décrémentation du compteur. 🎜await()
: Met le thread appelant cette méthode dans un état d'attente. Le thread principal ne sera pas réveillé tant que le compteur n'aura pas atteint 0. 🎜await(long, TimeUnit)
: Une stratégie de délai d'attente est ajoutée en fonction de la méthode await()
si le délai d'attente expire. Il n'y a toujours pas de résultat. Il réveillera directement le thread principal pour qu'il s'exécute. 🎜CountDownLatch
Le compteur est à 3 et les trois threads s'exécutent simultanément. La méthode countDownLatch.await()
est appelée dans le thread principal pour provoquer le blocage du thread principal. Après l'exécution de trois tâches de thread, la méthode countDownLatch.countDown()
sera appelée pour décrémenter le compteur. Lorsque les trois tâches de thread sont exécutées, la valeur du compteur atteint 0 et le thread principal est réveillé. 🎜🎜Remarque : La valeur du compteur doit être définie lors de la création d'une instance de CountDownLatch
Généralement, une utilisation relativement raisonnable est que la définition de la valeur nécessite un calcul raisonnable pour. faire la valeur du nombre Il est égal au nombre de threads qui doivent être parallélisés. Une fois l'exécution de chaque thread terminée, le nombre est décrémenté et enfin le thread principal est réveillé pour continuer l'exécution. 🎜
CountDownLatch
Si la valeur du nombre est définie pour être supérieure au nombre de threads, alors tous les threads finiront par être exécuté et le compte diminuera à 0. Ensuite, le thread principal sera toujours dans un état d'attente. 🎜CountDownLatch
Si la valeur du nombre est définie pour être inférieure au nombre de threads simultanés, alors le nombre peut avoir été décrémenté à 0 avant que certains threads n'aient terminé leur exécution, et le fil conducteur sera réveillé tôt. 🎜await()
Blocage du thread principal. 🎜🎜Remarque : await()
peut bloquer un ou plusieurs threads. Si plusieurs threads sont bloqués, lorsque le nombre est de 0, il se réveillera. tous les fils de discussion bloqués. 🎜
🎜 🎜🎜Scénarios d'utilisation🎜🎜Après avoir brièvement compris la fonction de CountDownLatch
, je pense que votre objectif ultime est de comprendre comment l'utiliser et dans quels scénarios il est plus approprié de l'utiliser. Suivant , je vais prendre une affaire de réconciliation. Analysons le scénario en détail. 🎜🎜Dans les circonstances actuelles, de nombreuses plateformes connecteront les transactions avec des canaux de paiement tels que UnionPay, WeChat et Alipay, le rapprochement est donc inévitable. Les rapprochements sont généralement traités tôt le matin de chaque jour. D'une part, la plupart des plates-formes ont des visites plus petites tôt le matin, et la pression du serveur est relativement détendue et les comptes sont plus raisonnables à cette heure-là. Il est également approprié d'effectuer le rapprochement à ce moment-là. Une opération de calcul de gros volume de données. 🎜🎜Il semble qu'aucun des points mentionnés ci-dessus n'ait été évoqué. Avant de procéder au rapprochement, il faut d'abord obtenir les fichiers de relevé via différents canaux de paiement. Alors comment opérer ? 🎜CountDownLatch
pour démarrer trois threads afin d'analyser leurs fichiers de réconciliation respectifs, et enfin le contenu du fichier. est converti dans le format unifié de données requis par l'entreprise et stocké dans la base de données. Une fois les trois tâches stockées dans la base de données, le thread principal est réveillé et marqué comme terminé, notifiant l'étape suivante pour commencer le travail. 🎜Réconciliation et règlement (troisième phase) : Une fois la saisie des données de la phase précédente terminée, ce qui doit être fait dans cette phase est de comparer Chaque Le fait qu'une transaction soit exacte ou non est généralement déterminé en comparant le montant de la transaction avec le numéro de commande et le canal de transaction. Si les montants sont cohérents, la transaction sera réglée avec succès. Sinon, la transaction sera considérée comme une transaction anormale et stockée. l'entrepôt pour le traitement. À partir de l'analyse du processus ci-dessus, nous pouvons concevoir un sémaphore CountDownLatch
计数,结合Semaphore
relativement raisonnable pour contrôler la concurrence et traiter simultanément les commandes de transactions de comparaison. Enfin, une fois toutes les commandes de transactions traitées, réveillez le thread principal pour marquer le rapprochement et notifier le. prochaine La comptabilité est effectuée par étapes.
Sortie (la quatrième étape) : Habituellement, la plateforme établira les comptes une fois le rapprochement terminé, c'est-à-dire selon le activités de la plateforme Les règles édictent des projets de loi pertinents pour permettre au personnel financier de réaliser des statistiques.
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!