,,JUC系列学习工具类CountDownLatch详解

,,JUC系列学习工具类CountDownLatch详解

这篇文章主要介绍了JUC系列学习工具类CountDownLatch详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可任意参考一下

前言:

项目中我们经常会遇到有时候需要等待其他线程完成任务后,主线程才能执行其他任务,那么我们将如何实现呢?

Join 解决方案

加入的工作原理是,检查线是否存活,如果存活则让当前线程永远等等,直到线线程终止,线程的notifyAll才会被调用。

具体实现

公共类JoinAThread扩展线程

{

@覆盖

公共无效运行(){

系统。出去。println(线程。当前线程().getName()

' 线程开始');

尝试{

线程。睡眠(100);

} catch (InterruptedException e) {

e。printstacktrace();

}

系统。出去。println(线程。当前线程().getName()

' 线程执行完毕');

}

}

公共类JoinBThread扩展线程

{

@覆盖

公共无效运行(){

系统。出去。println(线程。当前线程().getName()

' 线程开始');

尝试{

线程。睡眠(100);

} catch (InterruptedException e) {

e。printstacktrace();

}

系统。出去。println(线程。当前线程().getName()

' 线程执行完毕');

}

}

公共类联合测试

{

公共静态void main(String[] args)引发中断异常

{

JoinAThread joinA=new JoinAThread();

螺纹螺纹A=新线程(joinA,线程a’);

JoinBThread joinB=new JoinBThread();

螺纹螺纹B=新线程(joinB,线程b’);

threada。start();

threadb。start();

threada。join();

threadb。join();

System.out.println('子线程执行完成了,主线程Thread.currentThread().getName()'开始执行了');

}

}

执行结果

从结果中,我们可以看出只有子线程执行完成了,主线程才开始执行加入。的实现我们需要每个线程进行加入,如果存在多个线程,那么写起来会比较的繁琐,那么又没更新优化的方案了,答案是JUC下面的工具类CountDownLatch,也能完成同样的功能。

CountDownLatch 解决方案

具体实现

公共类CountDownLatchTest

{

私有静态记录器记录器=记录器工厂。获取记录器(countdownlatchtest。类);

公共静态void main(String[] args)引发中断异常

{

执行者服务exec=执行者。newcachedthreadpool();

final CountDownLatch CountDownLatch=new CountDownLatch(10);

for(int I=1;i=10i ){

exec.execute(() - {

尝试{

invokeServiec();

} catch(中断异常e)

{

logger.info('invoce服务错误,e);

}

最后

{

//计数器减一

countdownlatch。倒计时();

}

});

}

countdownlatch。await();

logger.info('所有的子线程执行完成,主线程Thread.currentThread().getName()'开始执行');

}

私有静态void invokeServiec()引发中断异常

{

伐木工。信息(线程。当前线程().getName()',开始执行任务');

线程。睡眠(300);

}

}

说明:CountDownLatch中有两个方法一个是等待()方法,调用这个方法的线程会被阻塞,另外一个是倒计时()方法,调用此方法会使计数器减一,当计数器的值为0时,调用等待()方法被阻塞的线程才会被唤醒。

执行结果:

原理说明

CountDownLatch是一个计数器锁存器,可以完成类似于阻塞当前线程的功能,即一个线程或多个线程等待,直到其他线程执行的操作完成。

基本原理

CountDownLatch

CountDownLatch在内部定义计数器和队列。在计数器递减到0之前,阻塞队列中的线程被挂起。当计数器递减到0时,阻塞队列中的所有线程都将被唤醒。计数器是一个符号,它可以指示一个任务、一个线程或一个倒计时定时器。

常用的方法

倒计时:用于将计数器减一,通常由执行任务的线程调用。await:用户线程处于等待状态,通常由主线程调用。

countDown

countDown实现方法如下:

说明:sync是AQS的队列,它调用AQS的releaseShared方法。其具体实现如下:

而releaseShared调用为CountDownLatch中的内部类sync中的tryReleaseShared方法,具体实现如下:

tryreaseshared(int)方法是将state属性减一的代码。CAS递减以保证原子性,会比较状态是否为C,如果是,则设置为nextc(自减一),如果不是C,则另一个线程已经在getState()方法和compareAndSetState()方法调用之间设置了状态,当前线程还没有成功设置state属性的值,则进入下一个循环,以此类推,直到成功设置state属性的值,即countDown()方法调用成功。

而doreleasshared方法调用AbstractQueuedSynchronizer(简称AQS)的doreleasshared方法,

注意:首先判断头节点不为空,也不是尾节点,说明等待队列中有等待唤醒的线程。这里需要注意的是,在等待队列中,等待线程不是存储在head节点中,而是一个空的node对象。真正的等待线程是从头节点的下一个节点开始存储的,所以会有一个头节点是否等于尾节点的判断。判断等待队列中有等待线程后,会清除头节点的状态信息,调用unparkSuccessor(Node)方法唤醒头节点的下一个节点,使其继续执行。它是以下unparkSuccessor(Node)方法的具体实现:

可以看到,unparkSuccessor(Node)方法的作用是唤醒离传入节点最近的等待线程,使其继续执行。

await

await方法实现如下:

await()方法调用了Sync对象的方法acquireSharedInterruptibly(int)方法,该方法的具体实现如下:

在doacquiresharedinterruptily(int)方法中,首先,使用当前线程创建一个共享模式节点。然后在for循环中,判断当前线程是否获得了执行权限,如果是(r=0判断),则将当前节点设置为头节点,唤醒共享模式的后续节点;否则,调用ShouldParkAfterFileDacquire(node,node)和parkAndCheckInterrupt()方法将当前线程置于“保持”状态。‘hold’状态由操作系统进行,可以避免线程的死循环和执行权的缺失,造成资源的浪费。在这里,线程处于等待状态,这意味着当线程被阻塞时,它被阻塞在这个位置。当多个线程调用await()方法并进入等待状态时,这些线程都会在这里等待。

总结

本文详细解释了JUC的工具类CountDownLatch。如果您有任何问题,请随时反馈。

以上就是本文关于JUC系列学习工具类CountDownLatch的详细讲解。有关JUC工具类CountDownLatch的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • word文档无法编辑是怎么回事-
  • 华为手机怎么设置返回键(华为手机下面的三个按键设置方法)
  • lumia950怎么样(Lumia950体验分享)
  • otg连接是什么意思(OTG连接手机方法)
  • 笔记本触摸板怎么右键(笔记本电脑触控板手势操作设置)
  • 真我x7怎么样(realme X7 系列体验)
  • 苹果的A16处理器有多强(苹果的A16处理器的介绍)
  • 小米互传怎么用(小米手机的连接与共享教程)
  • 怎么设置电脑桌面图标自动对齐 设置电脑桌面自动整理图标的方法
  • 宽带错误651最简单解决方法(处理宽带错误651的措施)
  • 大学生手机有什么推荐(大学生换手机攻略)
  • 天玑1100和骁龙778g哪个好(骁龙778G、天玑900、天玑1100购选建议)
  • yum update 升级报错的解决办法
  • Windows10禁用屏保教程
  • 连接wifi显示无互联网连接怎么办(无线连上了却不能上网处理绝招)
  • 留言与评论(共有 条评论)
       
    验证码: