在上一篇文章中说过使用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. tf随笔-1

    生成新的计算图,并完成常量初始化,在新的计算 图中完成加法计算 import tensorflow as tf g1=tf.Graph() with g1.as_default(): value=[1 ...

  2. opencv 边界确定函数

    多边形逼近,用嘴贴切的多边形标识 void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool c ...

  3. win10 135/445端口关闭

    135端口关闭 见[在 Windows 下关闭135/139/445端口的图文方法] 445端口关闭 打开控制面板-->网络和共享中心-->更改适配器设置-->右键点击正在使用的网卡 ...

  4. Oracle回收站 使用

    查询回收站 SELECT * FROM RECYCLEBIN; SELECT * FROM USER_RECYCLEBIN; --USER_RECYCLEBING与RECYCLEBIN是同义词,字段完 ...

  5. Struts2常用标签总结

    Struts2常用标签总结 一 介绍 1.Struts2的作用 Struts2标签库提供了主题.模板支持,极大地简化了视图页面的编写,而且,struts2的主题.模板都提供了很好的扩展性.实现了更好的 ...

  6. hibernate 多对多(many-to-many)

    多对多(many-to-many):在操作和性能方面都不太理想,所以多对多的映射使用较少,实际使用中最好转换成一对多的对象模型:hibernate会为我们创建中间关联表,转换成两个一对多. 1. E- ...

  7. Android开源框架-Annotation框架(以ViewMapping注解为例)

    Annotation 分类 1 标准 Annotation 包括Override, Deprecated, SuppressWarnings,标准 Annotation 是指 Java 自带的几个 A ...

  8. 剑指offer-第二章数据结构(数组,字符串,链表,树,栈与队列)及例题

    一.数组(最简单的数据结构) 定义:占据一块连续内存并按照顺序存储数据.创建时先指定大小,分配内存. 优点:时间效率高.实现简单的hash(下标为key,对应的数据为value) 缺点:空间效率差.如 ...

  9. [樹莓派]用mkusb来制作U盘启动安装Ubuntu 15.04

    之前實踐過這文章的描述,還可以成功:http://www.linuxdiyf.com/linux/12719.html,轉記錄餘下: 官方英文文档,教你在Ubuntu 15.04下使用mkusb来制作 ...

  10. Voting and Shuffling to Optimize Atomic Operations

    2iSome years ago I started work on my first CUDA implementation of the Multiparticle Collision Dynam ...