前言

JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch、CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行介绍。

CountDownLatch

CountDownLatch的主要作用是利用计数来保证线程的执行顺序(我自己的理解),有点像倒计时,当计数为0时某个线程才能开始执行。

CountDownLatch的主要方法很简单易用,包括:

  • CountDownLatch(int count) : 构造方法,需要传入计数的初始值
  • void await() : 调用者线程会被挂起,直到计数为0时才能执行
  • boolean await(long timeout, TimeUnit unit) : 同上,但是加入了超时参数,如果超时了计数还不为0,也会照样执行,避免了一直阻塞
  • void countDown() : 计数减一

示例代码:CountDownLatchTest.java

package juc.util;

import java.util.concurrent.CountDownLatch;

/**
* Created by puyangsky on 2017/1/7.
*/
public class CountDownLatchTest {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2); //用了匿名类创建线程
new Thread() {
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(2000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start(); new Thread() {
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(2000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start(); System.out.println("主线程"+Thread.currentThread().getName()+"正在执行");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程"+Thread.currentThread().getName()+"执行完毕");
}
}

结果:

主线程main正在执行
子线程Thread-0正在执行
子线程Thread-1正在执行
子线程Thread-0执行完毕
子线程Thread-1执行完毕
主线程main执行完毕

可以从结果中看到主线程本来是最先执行完,结果需要等两个子线程执行完才结束,就是因为调用了await方法。

CyclicBarrier

CyclicBarrier的意思是回环栅栏,作用是让一组线程同时到达某个时间节点。提供的重要方法如下:

  • CyclicBarrier(int parties) : 构造方法,传入线程组的数量
  • CyclicBarrier(int parties, Runnable barrierAction) : 构造方法,传入线程组的数量和当线程达到时间节点后要做的操作(由其中的某一个线程去执行)
  • int await() : 挂起当前线程,直到所有线程组中的线程都完成后继续执行,返回当前线程到达的次序
  • int await(long timeout, TimeUnit unit) : 加了一个超时参数

示例代码 CyclicBarrierTest.java:

package juc.util;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; /**
* Created by puyangsky on 2017/1/7.
*/
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("当前线程"+Thread.currentThread().getName());
}
});
for (int i=0;i<5;i++) {
new Task(barrier).start();
}
} static class Task extends Thread {
private CyclicBarrier barrier; public Task(CyclicBarrier barrier) {
this.barrier = barrier;
} public void run() {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
try {
Thread.sleep(3000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完成");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("全部线程执行完成");
}
}
}

结果:

子线程Thread-0正在执行
子线程Thread-3正在执行
子线程Thread-2正在执行
子线程Thread-1正在执行
子线程Thread-4正在执行
子线程Thread-3执行完成
子线程Thread-2执行完成
子线程Thread-0执行完成
子线程Thread-1执行完成
子线程Thread-4执行完成
当前线程Thread-4
全部线程执行完成
全部线程执行完成
全部线程执行完成
全部线程执行完成
全部线程执行完成

可以看到这一组线程是同步的去执行的。

Semaphore

Semaphore的意思是信号量,其作用是提供一个许可范围,只有获得了许可才能继续执行。

  • Semaphore(int permits):构造方法,需要传入许可数
  • Semaphore(int permits, boolean fair):fair为true时使用公平锁,false时使用非公平锁,具体在介绍AQS时讲解
  • void acquire():获得许可,可中断
  • void acquireUninterruptibly():不可中断的获取
  • void release():释放许可

示例 SemaphoreTest.java

package juc.util;

import java.util.concurrent.Semaphore;

/**
* Created by puyangsky on 2017/1/7.
*/
public class SemaphoreTest { public static void main(String[] args) {
Semaphore semaphore = new Semaphore(5);
for (int i = 0;i < 10;i++) {
new Worker(i, semaphore).start();
}
} static class Worker extends Thread {
private Semaphore semaphore;
private int num; public Worker(int num, Semaphore semaphore) {
this.semaphore = semaphore;
this.num = num;
} public void run() {
try { semaphore.acquire();
System.out.println("工人" + (this.num + 1) + "占用一个机器在生产...");
Thread.sleep(2000); System.out.println("工人" + (this.num + 1) + "释放一个机器...");
semaphore.release(); } catch (InterruptedException e) {
e.printStackTrace();
}
} }
}

结果

工人1占用一个机器在生产...
工人3占用一个机器在生产...
工人4占用一个机器在生产...
工人5占用一个机器在生产...
工人7占用一个机器在生产...
工人1释放一个机器...
工人5释放一个机器...
工人4释放一个机器...
工人7释放一个机器...
工人3释放一个机器...
工人8占用一个机器在生产...
工人9占用一个机器在生产...
工人10占用一个机器在生产...
工人6占用一个机器在生产...
工人2占用一个机器在生产...
工人9释放一个机器...
工人6释放一个机器...
工人10释放一个机器...
工人8释放一个机器...
工人2释放一个机器...

可以看到每次只有五个线程能运行,其他线程只有等待这五个线程释放许可后才能运行。

参考文章:

【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore的更多相关文章

  1. Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger

    在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...

  2. java.util.regex包下的Pattern类和Matcher类的使用总结

    一.介绍 Java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现1.Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不 ...

  3. Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...

  4. Java 获取指定包下的所有类

    package com.s.rest.util; import java.io.File; import java.io.FileFilter; import java.io.IOException; ...

  5. 并发包下常见的同步工具类(CountDownLatch,CyclicBarrier,Semaphore)

    在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并.这正是著名的map-reduce思 ...

  6. java 并发工具类CountDownLatch & CyclicBarrier

    一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...

  7. Java多线程_JUC包下的阻塞队列

    在前面我们提到了阻塞队列,也用过了LinkedBolckingQueue队列了,在这里,我们主要对 ArrayBlockingQueue,PriorityBlockingQueue,DelayQueu ...

  8. java多线程系列8 高级同步工具(2)CountDownLatch

    CountDownLatch,计数器的初始值为线程的数量.每当一个线程完成了自己的任务后, 计数器的值就会减1.当计数器值到达0时,它表示所有的线程已经完成了任务, 然后在闭锁上等待的线程就可以恢复执 ...

  9. java.util.regex包下的Pattern和Matcher详解(正则匹配)

    java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现(建议在阅读本文时,打开java API文档,当介绍到哪个方法时,查看java API中的方法说明,效果 ...

随机推荐

  1. js 停止事件冒泡 阻止浏览器的默认行为(阻止超连接 # )

    在前端开发工作中,由于浏览器兼容性等问题,我们会经常用到“停止事件冒泡”和“阻止浏览器默认行为”. 1..停止事件冒泡 JavaScript代码 //如果提供了事件对象,则这是一个非IE浏览器if ( ...

  2. 从Windows XP系统迁移到Windows 7,Windows 8开始

    Microsoft在2014年4月8日结束了Windows XP的支持.您的公司准备好了吗?如果您还没有迁移到Windows 7或8,那就要抓紧时间了.从现在起将不再向XP系统提供安全修补程序,而仍然 ...

  3. cache 浅析

    http://blog.chinaunix.net/uid-26817832-id-3244916.html   1. Cache Cache一词来源于法语,其原意是"藏匿处,隐秘的地方&q ...

  4. 用于主题检测的临时日志(b2d5c7b3-e3f6-4b0f-bfa4-a08e923eda9b - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

    这是一个未删除的临时日志.请手动删除它.(1c773d57-4f35-40cf-ad62-bd757d5fcfae - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

  5. Android UI系列-----时间、日期、Toasts和进度条Dialog

    您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...

  6. 轻松搞定面试中的二叉树题目(java&python)

    树是一种比较重要的数据结构,尤其是二叉树.二叉树是一种特殊的树,在二叉树中每个节点最多有两个子节点,一般称为左子节点和右子节点(或左孩子和右孩子),并且二叉树的子树有左右之分,其次序不能任意颠倒.二叉 ...

  7. MySQL的慢查询分析

    慢查询分析日最初是用来捕获比较“慢”的查询,在mysql5.1 + 版本中,慢查询的功能被加强,可以通过设置long_query_time为0来捕获所有的查询,而且查询的响应时间已经可以做到微妙级别. ...

  8. Qt 实现遥感图像显示时的连动效果

    遥感图像处理时少不了ENVI,用过ENVI的人都知道,打开图像时或图像处理完后,在缩略图上移动鼠标时,鼠标周围的图像信息会在大的视图中实时的显示,即大图会跟着小图中的鼠标移动,这即是图像的连动效果.如 ...

  9. SQL Server への接続を許可するファイアーウォール設定

    netsh advfirewall firewall add rule name="SQL Server Browser" protocol=UDP dir=in localpor ...

  10. 实现打印级别且带图片的Excel 方案

    导出二维数据excel,其实很简单,使用cvs就可以了.但是如果导出格式复杂带样式还带图片的怎么办?客户的要求有时就是这么变态.呵呵.如果使用.net,微软提供的有库,使用php好像也有现成的有库.我 ...