在上一篇文章中说过使用thread.join()方法、newSingleThreadExecutor单线程池来控制线程执行顺序。在文章的末尾我提出了一种构想,可否使用经典的生产者和消费者模型来控制执行顺序。在本文中,我将使用CountDownLatch来解决这个问题。

上图是countDownLatch的原理示意图。官方文档给出的解释是:CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。上图中线程A调用方法await()之后,进行阻塞,然后线程1执行任务完毕,数量减1,到最后线程2、3执行完毕,count=0。那么此时线程A等待了所有的线程执行完毕了任务。线程A状态复位,开始继续执行任务。

实现过程如下:

public class ThreadOrderTest {

    public static void main(String[] args) {
/**
* 创建线程类的时候,将上一个计数器和本线程计数器传入。运行前业务执行上一个计数器.await, 执行后本计数器.countDown。
*/ CountDownLatch num0 = new CountDownLatch(0);// 在这里count为0,表示该线程立马复位执行
CountDownLatch num1 = new CountDownLatch(1);// 在这里count为0,表示该线程立马复位执行
CountDownLatch num2 = new CountDownLatch(1);// 在这里count为0,表示该线程立马复位执行
Thread t1 = new Thread(new Count(num0, num1));
Thread t2 = new Thread(new Count(num1, num2));
Thread t3 = new Thread(new Count(num2, num2)); t1.start();
t2.start();
t3.start(); } static class Count implements Runnable { CountDownLatch num1;
CountDownLatch num2; /**
* 该构造器传递了上一个线程的计数器和当前线程的计数器
*
* @param num0
* @param num1
*/
public Count(CountDownLatch num1, CountDownLatch num2) {
super();
this.num1 = num1;
this.num2 = num2;
} @Override
public void run() {
try {
// 等待线程1执行完毕线程2开始执行,因为线程1开始立马就会执行(count=0)
num1.await();
System.out.println("开始执行线程:" + Thread.currentThread().getName());
num2.countDown();// 本线程计数器减少
} catch (InterruptedException e) {
e.printStackTrace();
} } } }
 

具体是怎么实现的呢:首先在创建线程的时候传递了Runnable对象,而该对象设置了两个参数,第一个参数保存了前一个线程的计数器,第二个线程保存了当前线程的计数器。线程1初始化的时候设置了线程的计数器为0,也就是说会立马执行任务,执行完毕,线程2 的计数器调用countdown()方法,立马从初始化的1变为0,同样开始执行,那么此时执行完毕,线程3计数器也减去1,开始执行任务。这样保证了三个线程的执行顺序。

下面是执行的结果:

开始执行线程:Thread-0
开始执行线程:Thread-1
开始执行线程:Thread-2

要说明的是,CountDownLatch存在不足的地方在于,要创建该对象的时候,我们会传递计数器的初始值,但是这个值一经设置,就再也无法修改了,因此计数器的使用时一次性的。这就是java.util.CountDownLatch的不足之处了吧!

   

 
 

关于CountDownLatch控制线程的执行顺序的更多相关文章

  1. jmeter 控制线程组执行顺序

    这个要配合全局变量.if和while来实现BeanShell取样器,全局变量:${__setProperty(newswitch,${switch1},)}if条件:"${__P(newsw ...

  2. join控制线程的执行循序 T1 -> T2 -> T3

    /** * 控制线程的执行循序 T1 -> T2 -> T3 * join实现 */ public static void join(){ Thread t1 = new Thread(( ...

  3. Java之CountDownLatch ---控制线程执行顺序

    一,类介绍 这是java.util.concurrent包里的一个同步辅助类,它有两个主要的常用方法  countDown()方法以及await()方法.在完成一组正在其他线程中执行的操作之前,它允许 ...

  4. jmeter的线程组执行顺序不以其出现的顺序发生变化

    jmeter可以同时配置多个线程组,那么他们的执行顺序是什么呢?和他们出现的顺序有什么关系呢? 先说下几个特殊的线程组:tearDown线程组和setUp线程组,tearDown线程组一定在最后执行, ...

  5. Jmeter 同一个测试计划下的多个线程组 执行顺序 希望调整为顺序执行

    用Jmeter做自动化测试,一个测试计划中添加多个线程组, 每个线程组的功能测试,希望是一个线程组执行完毕后,接着执行下一个线程组下的请求 Jmeter默认多个线程组之间是并行关系 需要在测试计划下勾 ...

  6. shell 脚本控制命令的执行顺序

    &&,||,(),{},& 五个符号的运用shell脚本执行命令的时候,有时候会依赖于前一个命令是否执行成功.而&&和||就是用来判断前一个命令执行效果的. 也 ...

  7. Qt 控制线程的顺序执行(使用QWaitCondition,并且线程类的run函数里记得加exec(),使得线程常驻)

    背景项目中用到多线程,对线程的执行顺序有要求: A.一个线程先收数据 B.一个线程处理数据 C.一个线程再将处理后的数据发送出去 要求三个线程按照ABC的顺序循环执行. 思路子类化多线程方法 重写子类 ...

  8. 【Java多线程系列四】控制线程执行顺序

    假设有线程1/线程2/线程3,线程3必须在线程1/线程2执行完成之后开始执行,有两种方式可实现 Thread类的join方法:使宿主线程阻塞指定时间或者直到寄生线程执行完毕 CountDownLatc ...

  9. Servlet 3.0 之@WebFilter怎么控制多个filter的执行顺序

    之前我们控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行   <!-- ...

随机推荐

  1. [置顶] kubernetes1.7新特性:新增StorageOS卷插件和Local持久存储

    背景介绍 在Kubernetes中卷的作用在于提供给POD存储,这些存储可以挂载到POD中的容器上,进而给容器提供存储. 从图中可以看到结构体PodSpec有个属性是Volumes,通过这个Volum ...

  2. c++指针初探

    业余时间准备重温一下c++,因为在阅读Android源码到native层的时候感觉有点吃力,只是在大学时候很不用心的学过c++,所以重温下以便打好一些编程基础知识,本篇就很简单的对c++的指针做初步的 ...

  3. [Beego] 内置的模板函数(不同格式的字符串和html的互转)

    在使用beego框架的时候,常常需要把不同形式的字符串转化为html,有时候为了安全考虑会将html转义,而有时候希望能显示html标签.在存储到db中后,再取出来的显示是原本的,即html标签不会生 ...

  4. (五)js数组方法二

    一:数组方法 var arr = []; 1.arr.push()//给数组末尾<添加>元素 2.arr.unshift()//给数组头部<添加>元素 3.arr.shift( ...

  5. HTML里 iframe跳转后关闭iframe

    if(window != top){      top.location.href = location.href;    }

  6. apt-get指令的autoclean,clean,autoremove的区别

    apt-get使用各用于处理apt包的公用程序集,我们可以用它来在线安装.卸载和升级软件包等,下面列出一些apt-get包含的常用的一些工具: 工具 说明 install 其后加上软件包名,用于安装一 ...

  7. Python基本特殊方法之__format__

    __format__()方法 __format__()传参方法:someobject.__format__(specification) specification为指定格式,当应用程序中出现&quo ...

  8. Django之模板继承

    为了在Django模板配置中减少代码的冗余,需使用模板继承 1. 语法 {% block classinfo %} {% endblock} 2. 步骤 (1)创建一个base.html把需要显示的页 ...

  9. 前端导出Excel

    1.首先,需要下载一个叫better-xlsx,的插件,以yarn 为例 ' yarn add better-xlsx --save '下载相关依赖包( npm 方式 ' npm i better-x ...

  10. matlab算法转为c语言注意事项

    matlab算法转为c语言后,影响c语言效率的关键在于multiword的产生,基于此会有multiword加减法和乘除法,极大消耗资源,减少甚至消除multiword很重要,需注意的是:算法中尽量减 ...