之所以把Latch与Barrier放在一起比较是因为他们给人一种相似的感觉。

他们都是阻塞一些行为直至某个事件发生,但Latch是等待某个事件发生,而Barrier是等待线程。

先比较一下JCIP中对二者的描述:

Latch

A latch is a synchronizer that can delay the progress of threads until it reaches its terminal state.

A latch acts as a gate: until the latch reaches the terminal state the gate is closed and no thread can pass, and in the terminal state the gate opens, allowing all threads to pass.

Once the latch reaches the terminal state, it cannot change state again, so it remains open forever.

Latches can be used to ensure that certain activities do not proceed until other one-time activities complete。

即,闭锁可以延迟线程执行直至达到相应的结束状态。闭锁就像一个大门,未到达结束状态相当于大门紧闭,不让任何线程通过。

而到达结束状态后,大门敞开,让所有的线程通过,但是一旦敞开后不会再关闭。

闭锁可以用来确保一些活动在某个事件发生后执行。

Barrier

CyclicBarrier allows a fixed number of parties to rendezvous repeatedly at a barrier point and is useful in parallel iterative algorithms that break down a problem into a fixed number of independent subproblems.

Threads call await when they reach the barrier point, and await blocks until all the threads have reached the barrier point.

If all threads meet at the barrier point, the barrier has been successfully passed, in which case all threads are released and the barrier is reset so it can be used again.

很多人都把Barrier直译为"栅栏",我也很喜欢这个叫法。

栅栏可以使一组执行在一处汇集,也就是说我们可以用栅栏将一个问题分解成多个独立的子问题,并在执行结束后在同一处进行汇集。

当线程到达汇集地后调用await,await方法会出现阻塞直至其他线程也到达汇集地。

如果所有的线程都到达就可以通过栅栏,也就是所有的线程得到释放,而且栅栏也可以被重新利用。

另外,下面javadoc中对二者之间区别的说明:

A CountDownLatch is initialized with a given count.

The await methods block until the current count reaches zero due to invocations of the countDown method, after which all waiting threads are released and any subsequent invocations of await return immediately.

This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.

闭锁从来都是带着事件的触发次数。

await方法会一直阻塞至countDown方法将次数变成0为止,所有的线程被释放才能进行后续的工作。

但这种现象只能出现一次,也就是说触发次数不会被重置。

如果你想要一个可重置次数的闭锁,那就用栅栏。

Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor.

When all sub-parts are complete, the coordinating thread will be able to pass through await.

(When threads must repeatedly count down in this way, instead use a CyclicBarrier.)

这种行为阻塞的典型用法之一就是将某个问题分成多个部分,每个部分用不同的线程负责,并记得减少闭锁设置的次数。

当所有线程的工作结束后将通过await方法造成的阻塞,如果我们需要反复进行这样的工作就需要使用栅栏。

好了,既然Doug Lea老师将同一个观点阐述了这么多遍,剩下就是放心大胆地使用了,也许我们将问题想得太复杂了。

下面贴出栗子,由一个startGate拦住所有线程的执行,当所有线程就绪完成后调用countDown将它们释放,而另一扇大门——endGate后面正等着计算执行时间,而endGate等待的事件由这些线程触发:

public class TestHarness {

public static long timeTasks(int nThreads, final Runnable task)

throws InterruptedException {

final CountDownLatch startGate = new CountDownLatch(1);

final CountDownLatch endGate = new CountDownLatch(nThreads);

for (int i = 0; i < nThreads; i++) {

Thread t = new Thread() {

public void run() {

try {

startGate.await();

try {

task.run();

} finally {

endGate.countDown();

}

} catch (InterruptedException ignored) {

}

}

};

t.start();

}

long start = System.nanoTime();

startGate.countDown();

endGate.await();

long end = System.nanoTime();

return end - start;

}

}

执行看看:

public static void main(String[] args) throws ExecutionException, InterruptedException {

System.out.println("cost :::"+TestHarness.timeTasks(10,new Runnable() {

@Override

public void run() {

int num = RandomUtils.nextInt(0,100);

if(num>50) try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("Alvez ::"+ num);

}

}));

}

接着试试栅栏,没有搞任何复杂的东西,注意countSupposed%partyCount,主要是想用这个体现一下栅栏是否可以反复使用多次。

如果countSupposed%partyCount的结果恰好为0,所有线程执行结束后,主线程也会正常结束。

反之则会一直阻塞下去,如果countSupposed%partyCount结果大于1且不为0,其结果就是我们看到"let's go to the barrier !!"出现的次数:

public static void barrierTest(int partyCount, int countSupposed) {

if(partyCount<1 || countSupposed < 1) throw new IllegalArgumentException();

final CyclicBarrier barrier = new CyclicBarrier(partyCount,new Runnable() {

@Override

public void run() {

System.out.println("let's go barrier !!");

}

});

System.out.println(countSupposed%partyCount==0?"let's show the smooth!!":"....but blocked");

for (int i = 0; i < countSupposed; i++) {

Runnable runnable = new Runnable() {

@Override

public void run() {

try {

barrier.await();

System.out.println(Thread.currentThread().getName() + " show!!");

} catch (InterruptedException e) {

e.printStackTrace();

} catch (BrokenBarrierException e) {

e.printStackTrace();

}

}

};

new Thread(runnable).start();

}

}

执行:

public static void main(String[] args) {

barrierTest(11, 20);

}

java barrier_Java - Latch和Barrier的区别相关推荐

  1. java aes php_php和java的aes默认加密算法有点区别及解决方法。

    1.php和java的aes默认加密算法有点区别,php能解密java加密的密文,但java不能解密php加密的密文.原因在于: 1.Java中AES加密与解密默认使用AES/ECB/PKCS5Pad ...

  2. java char的包装对象,Java 从Character和char的区别来学习自动拆箱装箱

    本文结构 1.Character和char 的区别: 2.自动拆箱装箱java 1.Character和char 的区别: Character是类,char基本数据类型.数组 在java中有三个类负责 ...

  3. c语言 python-C语言、Java语言和python语言的区别在哪里

    原标题:C语言.Java语言和python语言的区别在哪里 我们经常听到C语言.Java语言和python语言,那么这三者的区别在哪里呢?随着科技的进步以及新技术的推进,编程语言的种类也是越来越多,随 ...

  4. 1.8 Java字节流和字符流的区别,如何区分输入流和输出流?

    Java字节流和字符流的区别 首先我们先大概总结一下前面学习的内容,可分为以下几点: 以 Stream 结尾都是字节流,Reader 和 Writer 结尾都是字符流. InputStream 是所有 ...

  5. java中的异常种类和区别以及处理机制和区别

    java中的异常种类和区别以及处理机制和区别 按照异常需要处理的时机分为编译时异常(也叫强制性异常)也叫 CheckedException 和运行时异常(也叫非强制性异常)也叫 RuntimeExce ...

  6. java中ArrayList和LinkedList的区别

    首先来看ArrayList和LinkedList的集成类和接口的区别.// lang java public class ArrayList<E> extends AbstractList ...

  7. Java基础之equals和==的区别深入解析

    Java基础之equals和==的区别深入解析 以下是本文目录大纲 equals 和 == 的区别 equals 的重写 复写hashCode方法,有31这个数字的作用 1. equals 和 == ...

  8. java中Runnable和Callable的区别

    文章目录 运行机制 返回值的不同 Exception处理 java中Runnable和Callable的区别 在java的多线程开发中Runnable一直以来都是多线程的核心,而Callable是ja ...

  9. java中wait和sleep的区别

    文章目录 Wait和sleep的区别 唤醒wait和sleep java中wait和sleep的区别 在本篇文章中,我们将会讨论一下java中wait()和sleep()方法的区别.并讨论一下怎么使用 ...

最新文章

  1. 裴健等9名华人当选加拿大皇家学会院士
  2. LVM逻辑卷轴管理和磁盘配额实验
  3. pyqt5讲解9:时间模块timer和网页交互
  4. 【转】Maya Mel – Search String in String
  5. HMI使用自定义控件流程
  6. java编程线程怎么处理_java编程多线程并发处理的教程
  7. C++ 获取本机登陆过的QQ号码
  8. 《数学之美》—自然语言处理
  9. keil5破解(备忘,有需要的可以下载)
  10. 招聘工作总结(精选多篇)
  11. 网络邻居没有查看工作组计算机,为什么网上邻居内看不到计算机工作组
  12. DOGCOM路由器K2(7620A)for哆点(DRCOM)校园网-西安石油大学
  13. 撼龙图怎么开鸿蒙炁灵,《一人之下》藏金图怎么玩 撼龙藏金图高概率出绝世炁灵技巧...
  14. 用Python多线程抓取并验证代理
  15. matlab qua2d,matlab 几个关于GPS/INS和GPS/AHRS的程序 - 下载 - 搜珍网
  16. GGNN:GATED GRAPH SEQUENCE NEURAL NETWORKS
  17. CentOS 7.8 (2003) 发布,附下载地址
  18. 插入数据报错:ISAM error:no free disk space
  19. 【C进阶】之结构体类型( struct)
  20. 手机如何连接无线打印服务器,手机如何设置打印服务器的无线WiFi参数?(适用于 B1版)...

热门文章

  1. knockout+echarts实现图表展示
  2. google protobuf_protobuf 指南
  3. linux php不能写文件内容,php 在linux系统下写出文件问题
  4. 里面怎么模拟裂纹_警惕!你买的翡翠有裂纹吗?它能让翡翠的价值暴跌
  5. 2021年考计算机考研三战,2021考研的小伙伴有3条忠告一定要记得,这些都是历年实战经验...
  6. c语言程序兔子反之问题,C语言解决兔子产子问题代码及解析
  7. 【SSM面向CRUD编程专栏 3】关于黑马程序员最全SSM框架教程视频,P37集老师跳过的模块创建以及tomcat下载安装配置和运行等诸多问题
  8. 日常问题———Attempting to operate on hdfs namenode as root
  9. golang代理转发基础
  10. timeshift备份你的Linux系统