java多线程学习-java.util.concurrent详解(一) Latch/Barrier

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

    Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的Java多线程程序。从这篇blog起,我将跟大家一起共同学习这些新的Java多线程构件

1. CountDownLatch
    我们先来学习一下JDK1.5 API中关于这个类的详细介绍:
“一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。”

    这就是说,CountDownLatch可以用来管理一组相关的线程执行,只需在主线程中调用CountDownLatch 的await方法(一直阻塞),让各个线程调用countDown方法。当所有的线程都只需完countDown了,await也顺利返回,不再阻塞了。在这样情况下尤其适用:将一个任务分成若干线程执行,等到所有线程执行完,再进行汇总处理。

    下面我举一个非常简单的例子。 假设我们要打印1-100,最后再输出“Ok“。1-100的打印顺序不要求统一,只需保证“Ok“是在最后出现即可。

    解决方案:我们定义一个CountDownLatch,然后开10个线程分别打印(n-1)*10+1至(n-1)*10+10。主线程中调用await方法等待所有线程的执行完毕,每个线程执行完毕后都调用countDown方法。最后再await返回后打印“Ok”。

具体代码如下(本代码参考了JDK示例代码):
import java.util.concurrent.CountDownLatch;
/*** 示例:CountDownLatch的使用举例* Mail: ken@iamcoding.com* @author janeky*/
public class TestCountDownLatch {private static final int N = 10;public static void main(String[] args) throws InterruptedException {CountDownLatch doneSignal = new CountDownLatch(N);CountDownLatch startSignal = new CountDownLatch(1);//开始执行信号for (int i = 1; i <= N; i++) {new Thread(new Worker(i, doneSignal, startSignal)).start();//线程启动了}System.out.println("begin------------");startSignal.countDown();//开始执行啦doneSignal.await();//等待所有的线程执行完毕System.out.println("Ok");}static class Worker implements Runnable {private final CountDownLatch doneSignal;private final CountDownLatch startSignal;private int beginIndex;Worker(int beginIndex, CountDownLatch doneSignal,CountDownLatch startSignal) {this.startSignal = startSignal;this.beginIndex = beginIndex;this.doneSignal = doneSignal;}public void run() {try {startSignal.await(); //等待开始执行信号的发布beginIndex = (beginIndex - 1) * 10 + 1;for (int i = beginIndex; i <= beginIndex + 10; i++) {System.out.println(i);}} catch (InterruptedException e) {e.printStackTrace();} finally {doneSignal.countDown();}}}
}


    总结:CounDownLatch对于管理一组相关线程非常有用。上述示例代码中就形象地描述了两种使用情况。第一种是计算器为1,代表了两种状态,开关。第二种是计数器为N,代表等待N个操作完成。今后我们在编写多线程程序时,可以使用这个构件来管理一组独立线程的执行。

2. CyclicBarrier
    我们先来学习一下JDK1.5 API中关于这个类的详细介绍:
    “一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
    CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。

    我们在学习CountDownLatch的时候就提到了CyclicBarrier。两者究竟有什么联系呢?引用[JCIP]中的描述“The key difference is that with a barrier, all the threads must come together at a barrier point at the same time in order to proceed. Latches are for waiting for events; barriers are for waiting for other threads。CyclicBarrier等待所有的线程一起完成后再执行某个动作。这个功能CountDownLatch也同样可以实现。但是CountDownLatch更多时候是在等待某个事件的发生。在CyclicBarrier中,所有的线程调用await方法,等待其他线程都执行完。

    举一个很简单的例子, 今天晚上我们哥们4个去Happy。就互相通知了一下:晚上八点准时到xx酒吧门前集合,不见不散!。有个哥们住的近,早早就到了。有的事务繁忙,刚好踩点到了。无论怎样,先来的都不能独自行动,只能等待所有人

代码如下(参考了网上给的一些教程)
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TestCyclicBarrier {public static void main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();     final Random random=new Random();final CyclicBarrier barrier=new CyclicBarrier(4,new Runnable(){@Overridepublic void run() {System.out.println("大家都到齐了,开始happy去");}});for(int i=0;i<4;i++){exec.execute(new Runnable(){@Overridepublic void run() {try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"到了,其他哥们呢");try {barrier.await();//等待其他哥们} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}});}exec.shutdown();}}


    关于await方法要特别注意一下,它有可能在阻塞的过程中由于某些原因被中断

    总结:CyclicBarrier就是一个栅栏,等待所有线程到达后再执行相关的操作。barrier 在释放等待线程后可以重用。

更多的Java编程资料,欢迎访问我的blog: http://janeky.iteye.com,希望能够与你有更多的交流

未完待续

转载于:https://my.oschina.net/kkrgwbj/blog/398271

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

55种网页常用小技巧(转载)

55种网页常用小技巧乖的无聊 发表于 2005-4-18 13:18:09  1. οncοntextmenu"window.event.returnValuefalse" 将彻底屏蔽鼠标右键<table border οncοntextmenureturn(false)><td>no</table> 可用于Table2. <body onselectstart"retu…

Go学习笔记—锁(sync包)

并发安全和锁 1. sync.Mutex—实现互斥锁 var lock sync.Mutex var x int func add() { //这样&#xff0c;在多个goroutine同时访问x时&#xff0c;才不会造成x错误for i : 0; i < 5000; i {lock.Lock() // 加锁x x 1lock.Unlock() // 解锁} }2. sync.RWMutex—实现读写…

switch…case语句注意事项

1、 case 的值必须是常量表达式&#xff0c;不允许使用变量。2、如果一个 case 子句为空&#xff0c;就可以从这个 case 跳到下一个 case 上&#xff0c;这样就可以用相同的方式处理两个或多个 case 子句了(不需要 goto 语句)。3、在C#中&#xff0c;可以把字符串用作测试变量。…

Java Websocket实例

2019独角兽企业重金招聘Python工程师标准>>> 介绍 现很多网站为了实现即时通讯&#xff0c;所用的技术都是轮询(polling)。轮询是在特定的的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由浏览器对服务器发出HTTP request&#xff0c;然后由服务器返回最新…

LeetCode 287. 寻找重复数

给定一个包含 n 1 个整数的数组 nums&#xff0c;其数字都在 1 到 n 之间&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。假设只有一个重复的整数&#xff0c;找出这个重复的数。 示例 1: 输入: [1,3,4,2,2]输出: 2示例 2: 输入: [3,1,3,4,2]输…

Go学习笔记—并发高级

Go并发机制 ​ 协程&#xff1a;一个线程可以对应多个协程&#xff0c;协程串行运行在用户空间。协程运行在线程之上&#xff0c;当一个协程执行完成后&#xff0c;可以选择主动让出&#xff0c;让另一个协程运行在当前线程之上。协程并没有增加线程数量&#xff0c;只是在线程…

设计模式C++学习笔记之十三(Decorator装饰模式)

装饰模式&#xff0c;动态地给一个对象添加一些额外的职责。就增加功能来说&#xff0c;Decorator模式相比生成子类更为灵活。 13.1.解释 main()&#xff0c;老爸 ISchoolReport&#xff0c;成绩单接口 CFourthGradeSchoolReport&#xff0c;四年级成绩单 ReportDecorator&…

Android应用开发相关下载资源(2014/12/14更新)

官方终于发布了Android Studio正式版&#xff0c;Android Studio将会成为推荐使用的主要Android开发工具. (1)Android SDK (Android SDK主安装包&#xff0c;包含SDK Manager、AVD Manager、工具包tools&#xff0c;释放后的根文件夹为android-sdk-windows): revision 23.0.2ht…

分层在深一步学习

前几天自己写了写DAL层,还有Model!理解到在DAL中主要是写的数据操作,而这些操作又是基于DbHelper这个基类!而数据库的访问则写在了这个基类中,目前还没研究BLL层,不过知道其中写的是算法!在Model中写的对象的属性,还有数据的规范(据说是,呵呵).自己对分层开发很感兴趣!呵呵,加油…

程序员编程艺术:第二章、字符串是否包含问题

程序员编程艺术&#xff1a;第二章、字符串是否包含及相关问题扩展 作者&#xff1a;July&#xff0c;yansha。时间&#xff1a;二零一一年四月二十三日。致谢&#xff1a;老梦&#xff0c;nossiac&#xff0c;Hession&#xff0c;Oliver&#xff0c;luuillu&#xff0c;雨翔&a…

LeetCode—207. 课程表

207. 课程表 题目描述&#xff1a;你这个学期必须选修 numCourses 门课程&#xff0c;记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出&#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示如果要学习课程 ai…

详解为何在嵌套ESXi环境下要求开启Promiscuous Mode

原文链接&#xff1a;http://bbs.vmanager.cn/forum.php?modviewthread&tid8688&fromuid35445在嵌套环境中&#xff0c;有时候网路不通&#xff0c;此时&#xff0c;调整Promiscuous Mode选项为Accept之后&#xff0c;网路就可以通了。之前只是知道这个选项可以保证嵌…

Rapidmind计算库性能测试

rapidmind.net提供了免费的计算库下载&#xff0c;目的是使用C metaprogramming将计算与硬件平台隔离开来&#xff0c;它提供一套运行库做底层的优化工作。为了测试其真正的性能&#xff0c;以便于在未来的渲染器中使用&#xff0c;我做了一个简单的性能测试程序&#xff0c;将…

VMware 怎么进入BIOS

2019独角兽企业重金招聘Python工程师标准>>> 虚拟机(Vmware)引导Linux虚拟机时&#xff0c;需要设置成光盘启动来引导系统&#xff0c;但是vmware默认是硬盘启动&#xff0c;所以会启动不了或者别的问题存在。所以要进bios里面设置成开机的启动顺序&#xff0c;要将…

LeetCode—208. 实现 Trie (前缀树)

208. 实现 Trie (前缀树) 题目描述&#xff1a;Trie&#xff08;发音类似 “try”&#xff09;或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动补完和拼写检查。 请你实现 Trie 类…

SQL入侵恢复XP_CMDSHLL与开3389

一,用SQL连接器恢复XP_CMDSHLLE的命令 &#xff08;1&#xff09;sp_addextendedproc xp_cmdshell,dllnamexplog70.dll &#xff08;2&#xff09;首先在SqlExec Sunx Version的Format选项里填上%s&#xff0c;在CMD选项里输入 sp_addextendedproc xp_cmdshell,xpsql70.dll 去除…

java中long类型转换为int类型

由int类型转换为long类型是向上转换&#xff0c;可以直接进行隐式转换&#xff0c;但由long类型转换为int类型是向下转换&#xff0c;可能会出现数据溢出情况&#xff1a; 主要以下几种转换方法&#xff0c;供参考&#xff1a;一、强制类型转换 [java] long ll 300000; in…

中国最好的电子商务平台,75商务网成功上线

中国B2B电子商务网站多年处于停滞不前&#xff0c;行业垄断现象&#xff0c;而且非常专注于B2B方向发展&#xff0c;没有其他业务范围可以拓展。http://www.755563.com/ “ 75商务网 ”看到其中亮点&#xff0c;在原有B2B基础上增加新型模式&#xff0c;变成B2B2C形式&#xff…

SVN钩子HOOK设置自动备份,服务本地可以看到所有更新内容。

可以实现SVN本机备份。或者其他备份。关键是可以保持有一份最新的SVN文件可以查看。 实现SVN与WEB同步,可以CO一个出来,也可以直接用自动更新web目录的方法&#xff0c;我们要在svn版本库中配置钩子来实现&#xff0c;就是创建一个post-commit的配置文件&#xff0c;对其进行简…

LeetCode—33. 搜索旋转排序数组

33. 搜索旋转排序数组 题目描述&#xff1a;整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums…