java多线程应用场景不少,有时自己编写代码又不太容易实现,好在concurrent包提供了不少实现类,还有google的guava包更是提供了一些最佳实践,这让我们在面对一些多线程的场景时,有了不少的选择。

这里主要是看几个涉及到多线程等待的工具类。

一 CountDownLatch 一个或多个线程等待其他线程达到某一个目标后,再进行自己的下一步工作。而被等待的“其他线程”达到这个目标后,也继续自己下面的任务

看起来虽然比较绕,但是还算能理解。看几个场景:
跑步比赛,裁判需要等到所有的运动员(“其他线程”)都跑到终点(达到目标),才能去算排名和颁奖。
模拟并发,我需要启动100个线程去同时访问某一个地址,我希望它们能同时并发,而不是一个一个的去执行。

用法很简单,只有一个构造方法用于指明计数数量,然后就是await用于线程等待,countDown用于将计数器减1.
  1. public CountDownLatch(int count) { }; //参数count为计数值
  1. public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
  2. public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
  3. public void countDown() { }; //将count值减1

工作原理就是让“其他线程”在合适的地方进行await等待,直到所有线程达到了某一个目标,然后再一起释放。

看代码:
赛跑的代码
  1. import java.util.Random;
  2. import java.util.concurrent.CountDownLatch;
  3.  
  4. /**
  5. * Created by wuwf on 17/7/17.
  6. * 一个线程或多个线程等待其他线程运行达到某一目标后进行自己的下一步工作,而被等待的“其他线程”达到这个目标后继续自己下面的任务。
  7. * <p/>
  8. *
  9. */
  10. public class TestCountDownLatch {
  11. private CountDownLatch countDownLatch = new CountDownLatch(4);
  12.  
  13. public static void main(String[] args) {
  14. TestCountDownLatch testCountDownLatch = new TestCountDownLatch();
  15. testCountDownLatch.begin();
  16. }
  17.  
  18. /**
  19. * 运动员
  20. */
  21. private class Runner implements Runnable {
  22. private int result;
  23. public Runner(int result) {
  24. this.result = result;
  25. }
  26.  
  27. @Override
  28. public void run() {
  29. try {
  30. //模拟跑了多少秒,1-3之间随机一个数
  31. Thread.sleep(result * 1000);
  32.  
  33. System.out.println("运动员" + Thread.currentThread().getId() + "跑了" + result + "秒");
  34.  
  35. //跑完了就计数器减1
  36. countDownLatch.countDown();
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  42.  
  43. private void begin() {
  44. System.out.println("赛跑开始");
  45.  
  46. Random random = new Random(System.currentTimeMillis());
  47. for (int i = 0; i < 4; i++) {
  48. //随机设置每个运动员跑多少秒结束
  49. int result = random.nextInt(3) + 1;
  50. new Thread(new Runner(result)).start();
  51. }
  52.  
  53. try {
  54. countDownLatch.await();
  55. } catch (InterruptedException e) {
  56. e.printStackTrace();
  57. }
  58. System.out.println("所有人都跑完了,裁判开始算成绩");
  59. }
  60. }

这段代码就是一个主线程,等待其他多个子线程完成某个任务后,再去执行下面的逻辑。

模拟并发的代码

  1. import java.util.concurrent.CountDownLatch;
  2.  
  3. /**
  4. * Created by wuwf on 17/7/18.
  5. * 模拟N个线程同时启动
  6. */
  7. public class TestManyThread {
  8. private CountDownLatch countDownLatch = new CountDownLatch(200);
  9.  
  10. public static void main(String[] args) {
  11. new TestManyThread().begin();
  12. }
  13.  
  14. public void begin() {
  15. for (int i = 0; i < 200; i++) {
  16. new Thread(new UserThread()).start();
  17. countDownLatch.countDown();
  18. }
  19.  
  20. try {
  21. Thread.sleep(2000);
  22. System.out.println("线程并发");
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27.  
  28. private class UserThread implements Runnable {
  29.  
  30. @Override
  31. public void run() {
  32. try {
  33. //等待所有线程
  34. countDownLatch.await();
  35.  
  36. //TODO 在这里做客户端请求,譬如访问数据库之类的操作
  37.  
  38. } catch (InterruptedException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
  43. }

需要注意,上面两个例子是不同的方式,一个是主线程等待其他线程达到某个目标后,自己再去完成一件事;第二个例子是多个线程达到某个目标后,继续完成各自的后续任务。
其中由第二个例子引申出下一个并发工具类。


二 CyclicBarrier 实现让一组线程等待至某个状态之后再全部同时执行,而且当所有等待线程被释放后,CyclicBarrier可以被重复使用。

这个也很好理解,大家约定好一起到XX地址汇合,所有人都到了以后再一起去吃饭。
它有两个构造方法
  1. public CyclicBarrier(int parties, Runnable barrierAction) {
  2. }
  3.  
  4. public CyclicBarrier(int parties) {
  5. }

parties代表让多少个线程等待,Runnable属性是一个新线程,代表所有线程达到状态、等待完毕后,会执行的任务。
同样的也有两个await方法

  1. public int await() throws InterruptedException, BrokenBarrierException { };
  2. public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { };

第一个代表线程挂起开始等待,一直等到达到目标状态,第二个代表等待一段指定的时间后,如果还没释放,就直接继续执行,不await了。

看代码
  1. import java.util.concurrent.CyclicBarrier;
  2.  
  3. /**
  4. * Created by wuwf on 17/7/18.
  5. */
  6. public class TestCyclicBarrier {
  7. private CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
  8.  
  9. public static void main(String[] args) {
  10. new TestCyclicBarrier().begin();
  11. }
  12.  
  13. public void begin() {
  14. for (int i = 0; i < 5; i++) {
  15. new Thread(new Student()).start();
  16. }
  17.  
  18. }
  19.  
  20. private class Student implements Runnable {
  21.  
  22. @Override
  23. public void run() {
  24. try {
  25. System.out.println("学生" + Thread.currentThread().getId() + "正在赶往XX饭店的路上");
  26. Thread.sleep(2000);
  27. //到了就等着,等其他人都到了,就进饭店
  28. cyclicBarrier.await();
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. }
  32.  
  33. System.out.println("大家都到了,进去吃饭吧!");
  34. }
  35. }
  36. }


可以看到这个工具类的目的,主要是为了限制一组线程在达到某个条件后,强制进行等待,直到最后一个线程也执行完await之前的逻辑后,再所有线程一起走await后面的。
与CountDownLatch不同,它不需要去自己维护那个CountDown每次减1的操作,与之相反,CyclicBarrier是每次都加1,直到加到构造方法里设定的值。
所以使用这个类一样可以完成上面CountDownLatch的第二个例子,就是模拟N个线程并发,而且用法比CountDownLatch更简单一些。

要说起这两个类的区别,我觉得更多的初衷是CountDownLatch目的是让一个线程等待其他N个线程达到某个条件后,自己再去做某个事(通过CyclicBarrier的第二个构造方法,在新线程里做事可以达到同样的效果)。而CyclicBarrier的目的是让N多线程互相等待直到所有的都达到某个状态,然后这N个线程再继续执行各自后续(通过CountDownLatch在某些场合也能完成类似的效果)。
根据场景选择更简单的那个就好。



Java并发编程之CountDownLatch,CyclicBarrier实现一组线程相互等待、唤醒的更多相关文章

  1. Java 并发编程中的 CyclicBarrier 用于一组线程互相等待

    Java 5 引入的 Concurrent 并发库软件包中的 CyclicBarrier 是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point) ...

  2. Java并发编程之CountDownLatch

    一.场景描述 在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景 例如:百米赛跑,十名运动员同时起跑,由于速度的快慢,肯定有先到达和后到达的,而终点有个统计成绩的仪器,当所有选手到达终点时 ...

  3. Java并发编程之CountDownLatch的用法

    一.含义 CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能.CountDownLatch是一个同步的辅助类,它可以允许一个或多个线程等待, ...

  4. Java并发编程之CyclicBarrier

    一.场景描述 有四个游戏玩家玩游戏,游戏有三个关卡,每个关卡必须要所有玩家都到达后才能允许通过.其实这个场景里的玩家中如果有玩家A先到了关卡1,他必须等到其他所有玩家都到达关卡1时才能通过,也就是说线 ...

  5. Java并发编程之CAS

    CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...

  6. Java并发编程之CAS第一篇-什么是CAS

    Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl.从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是<凯哥 ...

  7. Java并发编程之CAS二源码追根溯源

    Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...

  8. Java并发编程之CAS第三篇-CAS的缺点及解决办法

    Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...

  9. Java并发编程之set集合的线程安全类你知道吗

    Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...

随机推荐

  1. 20145329 《Java程序设计》实验五总结

    实验内容: 1.用老师代码编写,实现服务器与客户端. 2.客户端与服务器连接 3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务器的公钥加密,计算明文的Hash函数值,一起传 ...

  2. Jquery2 基础核心

    学习要点: 1.代码风格 2.加载模式 3.对象互换 4.多个库之间的冲突 本节简单的介绍一下jQuery 一些核心的问题. 一.代码风格 在jQuery程序中,不管是页面元素的选择.内置的功能函数, ...

  3. Qt+VS编译出错:Two or more files with the name of moc_Geometry.cpp will produce outputs to the same location

    warning MSB8027: Two or more files with the name of moc_Geometry.cpp will produce outputs to the sam ...

  4. LeetCode——Largest Rectangle in Histogram

    Question Given n non-negative integers representing the histogram's bar height where the width of ea ...

  5. easyui combobox 拼音检索快捷选择输入

    easyui combobox 拼音检索快捷选择输入 效果如图   $.ajax({ url: UserActionUrl + '?action=listuserworktype', dataType ...

  6. linux一键安装mysql脚本

    #!/bin/sh if [ -s /etc/my.cnf ];then rm -rf /etc/my.cnf fi echo "------------------------------ ...

  7. u-boot-2015.07 make xxx_config 分析

    1.u-boot编译脚本:mk.sh #! /bin/sh export PATH=$PATH:/opt/ti-sdk-am335x-evm-08.00.00.00/linux-devkit/sysr ...

  8. 如何在 Ubuntu 中安装 QGit 客户端

    QGit是一款由Marco Costalba用Qt和C++写的开源的图形界面 Git 客户端.它是一款可以在图形界面环境下更好地提供浏览版本历史.查看提交记录和文件补丁的客户端.它利用git命令行来执 ...

  9. bzoj1005: [HNOI2008]明明的烦恼 prufer序列

    https://www.lydsy.com/JudgeOnline/problem.php?id=1005 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的 ...

  10. dom&bom的起源,方法,内容,应用

    Document Object Model的历史可以追溯至1990年代后期微软与Netscape的"浏览器大战"(browser wars),双方为了在JavaScript与JSc ...