阻塞与唤醒方式的区别

CountDownLatch计数方式

CountDownLatch是减计数。调用await()后线程阻塞。调用countDown()方法后计数减一,当计数为零时,调用await()的线程被唤醒。

CountDownLatch应用场景为:

一个或一组线程等待另一组线程完成操作后恢复执行

CountDownLatch例子: 模拟赛跑

开始时一组运动员线程等待begin计数器(初始值为1),当主线程调用begin.countDown()后begin减1,计数器为0,这一组运动员线程同时起跑。主线程等待end计数器(初始值为10)。一个运动员线程到达终点后,调用end.countDown(),end计数器减1。当所有运动员都到达终点后,end计数器为0,主线程恢复执行。

package CountDownLatch;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class RaceSimulation {
public static void main(String args[]){
//比赛开始的倒数锁
CountDownLatch begin=new CountDownLatch(1);
//比赛结束的倒数锁
CountDownLatch end=new CountDownLatch(10);
//十个选手跑步线程
final ExecutorService exec = Executors.newFixedThreadPool(10); for(int index= 0;index<10;++index){
final int NO=index+1;
Runnable run = new Runnable(){
@Override
public void run() {
try{
//如果计数不为0,则一直等待
//如果当前计数为0,此线程立即执行
begin.await();
Thread.sleep((long)(Math.random()*10000));
System.out.println("No."+NO+" arrived");
}catch(InterruptedException e){
e.printStackTrace();
}finally{
//每个选手到达终点时,end就减1
end.countDown();
}
}
};
exec.submit(run);
}
System.out.println("游戏开始:");
//begin减1,开始游戏
begin.countDown();
//等待end变为0,即所有选手到达终点
try {
end.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("游戏结束");
exec.shutdown();
}
}

CyclicBarrier计数方式

CyclicBarrier是加计数。调用await()后线程阻塞计数器加1,当所有线程都到达屏障被阻塞后,这一组线程才一起恢复执行。

CyclicBarrier的应用场景

一组线程到达一个屏障(即执行CyclicBarrier.await())时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。

CyclicBarier的例子

package cyclicBarrier;

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 CyclicBarrierDemo {
public static void main(String[] args) {
int N=4;
CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() {
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作");
}
});
ExecutorService exec=Executors.newFixedThreadPool(4);
for(int i=0;i<N;++i) {
Runnable r=()->{
try {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
//用睡眠代替线程的操作
Thread.sleep(new Random().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
cyclicBarrier.await();
System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
exec.submit(r);
}
exec.shutdown();
}
}

是否可以重用

  1. CountDownLatch不可以重用

  2. CyclicBarrier可以重用

package cyclicBarrier;

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 CyclicBarrierDemo {
public static void main(String[] args) {
int N=4;
CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() {
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作");
}
});
ExecutorService exec1=Executors.newFixedThreadPool(4);
for(int i=0;i<N;++i) {
Runnable r=()->{
try {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
//用睡眠代替线程的操作
Thread.sleep(new Random().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
cyclicBarrier.await();
System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
exec1.submit(r);
}
exec1.shutdown();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("CyclicBarrier重用");
ExecutorService exec2=Executors.newFixedThreadPool(4); for(int i=0;i<N;++i) {
Runnable r=()->{
try {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
//用睡眠代替线程的操作
Thread.sleep(new Random().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
cyclicBarrier.await();
System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
exec2.submit(r);
}
exec2.shutdown();
}
}

CyclicBarrier与CountDownLatch区别的更多相关文章

  1. CyclicBarrier和CountDownLatch区别

    这两天写多线程时,用到了CyclicBarrier,下意识的认为CyclicBarrier和CountDownLatch作用很像,就翻阅资料查了一下,说一下他们的区别吧 CyclicBarrier和C ...

  2. JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch

    今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...

  3. JAVA多线程学习十三 - 同步工具CyclicBarrier与CountDownLatch

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

  4. CountDownLatch、CyclicBarrier、Semaphore 区别

    CountDownLatch.CyclicBarrier.Semaphore 区别: CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: Coun ...

  5. JDK源码分析之concurrent包(四) -- CyclicBarrier与CountDownLatch

    上一篇我们主要通过ExecutorCompletionService与FutureTask类的源码,对Future模型体系的原理做了了解,本篇开始解读concurrent包中的工具类的源码.首先来看两 ...

  6. CyclicBarrier和CountDownLatch的差别

    CyclicBarrier和CountDownLatch都用多个线程之间的同步,共同点:同时有N个线程在 CyclicBarrier(CountDownLatch) 等待上等待时,CyclicBarr ...

  7. Java并发之CyclicBarrier、CountDownLatch、Phaser

    在Java多线程编程中,经常会需要我们控制并发流程,等其他线程执行完毕,或者分阶段执行.Java在1.5的juc中引入了CountDownLatch和CyclicBarrier,1.7中又引入了Pha ...

  8. 《java.util.concurrent 包源码阅读》21 CyclicBarrier和CountDownLatch

    CyclicBarrier是一个用于线程同步的辅助类,它允许一组线程等待彼此,直到所有线程都到达集合点,然后执行某个设定的任务. 现实中有个很好的例子来形容:几个人约定了某个地方集中,然后一起出发去旅 ...

  9. 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法

    数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...

随机推荐

  1. 论Java中的抽象类与接口

    目录 抽象类和抽象方法 定义 与普通类的区别以及注意点: 抽象类的作用 接口 定义 示例 注意 作用 最后:接口与抽象类的异同 使用场景 借鉴 抽象类和抽象方法 定义 抽象方法和抽象类都必须被abst ...

  2. Go语言教程之结构体

    Hello,大家好,我是小栈君,最近因为工作的事情延误了一点分享的进度,但是我会尽量抽时间分享关于IT干货知识,还希望大家能够持续关注"IT干货栈"哦. 闲话不多说,今天给大家继续 ...

  3. SQL Server2012高可用之日志传送测试

    (一)日志传送架构 (1.1)相关服务器 主服务器   :用于生产的服务器,上面运行这生产SQL Server数据库: 辅助服务器:用于存放主服务器上数据库的一个“镜像”数据库: 监控服务器:用来监控 ...

  4. 【ARM】---关于ARM内核与架构的解释

    本文摘自某论坛某位大神的一段回复,经典至极,copy来己用! 只要你玩过ARM内核的芯片,那么关于内核和架构,我想应该或多或少的困惑过你,看了下面的介绍,你应该会清楚很多! 好比你盖房子,刚开始因为水 ...

  5. KVM虚拟化基础

    关于虚拟化 什么是虚拟化 在计算机技术中,虚拟化(技术)或虚拟技术(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源(CPU.内存.磁盘空间.网络适配器等),予以抽象. ...

  6. ASP.NET MVC4 使用UEditor富文本

    原帖:http://user.qzone.qq.com/369175376/infocenter?ptlang=2052     第一步:先到http://ueditor.baidu.com/webs ...

  7. airtest启用本地python环境的方法

    实现目标,air如果想引用第三方python库,则需要在本地python欢迎执行运行 1.打开设置,红色箭头处,选择本地python路径 2.安装air的两个核心库airtest和pocoui 安装方 ...

  8. 同一个环境同时使用python2和python3的方法

    1.首先安装好p2和p3,配置好环境变量.在CMD内执行python返回版本号,返回结果根据配置的环境变量而定,如果p2的环境变量配置在前面,则返回p2的版本号,反之则p3 2.然后把各版本目录下的p ...

  9. Linux 常用工具openssh之ssh-add

    前言 ssh-add命令是把专用密钥添加到ssh-agent的高速缓存中,从而提高ssh的认证速度 语法 ssh-add [-cDdLlXx] [-t life] [file ...] 选项 -D:删 ...

  10. Linux防火墙之iptables入门

    一.防火墙的概念 什么是防火墙?防火墙是一台或一组设备,用以在网络间实施访问控制策略:事实上一个防火墙能够包含OSI模型中的很多层,并且可能会涉及进行数据包过滤的设备,它可以实施数据包检查和过滤,在更 ...