在Java中什么是 循环壁垒
Java中的 CyclicBarrier 是JDK 5中引入的一个同步器 , 与其他并发工具如Counting Semaphore、BlockingQueue、ConcurrentHashMap 等一起 放在 java.util.Concurrent 包中 。CyclicBarrier 类似于 我们在上一篇文章 《 什么是Java中的CountDownLatch 》中看到的CountDownLatch ,它允许多个线程在进行操作前互相等待(屏障)。CountDownLatch和CyclicBarrier之间的区别也是Java中非常流行的多线程面试问题 。CyclicBarrier 是一个并发程序的自然要求,因为它可以在单个任务完成后用于执行任务的最后部分。
所有等待 对方到达障碍物的线程被称为当事方,CyclicBarrier 被初始化为等待的当事方数量,线程通过调用 CyclicBarrier.await() 方法 来等待对方 , 该 方法 在Java中是一个阻塞方法 ,阻塞直到所有线程或当事方调用await()。
一般来说,调用 await() 就是喊出线程正在等待屏障。 await() 是一个阻塞式调用,但可以超时或 被其他线程打断。
在这个Java并发教程中,我们将看到什么是Java中的CyclicBarrier ,以及一个CyclicBarrier的例子 ,在这个例子中,三个线程将在进一步进行之前相互等待。
而且,如果你真的想掌握Java多线程和并发,那么我还建议你 看看Udemy上Michael Pogrebinsy的**Java多线程、并发和性能优化** 课程。这是一门高级课程,旨在成为Java多线程、并发和并行编程方面的专家,重点强调高性能
区别于 倒计时锁存器(CountDownLatch 和 循环阻隔 在Java中的区别
在上一篇文章 中,我们要看到CountDownLatch如何 被用来 实现多个线程 的 相互等待。如果你看一下 CyclicBarrier ,它也做了同样的事情,但不同的是, 一旦计数达到零,你 就 不能重复使用 CountDownLatch ,而你可以 通过调用 reset() 方法 重复使用 CyclicBarrier, 将Barrier重置到初始状态。
这意味着 CountDownLatch 适用于一次性事件,如应用程序的启动时间,而 CyclicBarrier 可用于经常性事件,如同时计算一个大问题的解决方案等。如果你想了解更多关于Java中线程和并发的信息,你也可以查看我的帖子:在Java中何时使用易失性变量和Java中的同步如何工作。
如何在Java中使用CyclicBarrier - 示例
现在我们知道了什么是Java中的CyclicBarrier,现在是时候看看Java中CyclicBarrier的例子了。下面是一个 Java中 CyclicBarrier的简单例子 ,我们 用3个当事方 初始化 了CyclicBarrier ,这意味着为了跨越障碍,3个线程需要调用 await() 方法。
每个线程都在短时间内调用await方法,但在所有3个线程都到达障碍物之前,它们不会继续进行,一旦所有线程都到达障碍物,障碍物就会被代理,每个线程 都从这一点上开始执行它们。以下是 Java中CyclicBarrier的例子,它的输出非常清楚 。
**import** java.util.concurrent.BrokenBarrierException;
**import** java.util.concurrent.CyclicBarrier;
**import** java.util.logging.Level;
**import** java.util.logging.Logger;
/\*\*
\* Java程序展示如何在Java中使用CyclicBarrier。CyclicBarrier是一个
\* 在Java 5并发包中增加的新的并发工具。
\*
\* @author Javin Paul
\*/
**public** **class**CyclicBarrierExample{
*//Runnable task for each thread*
**private** **static** **class**Task**implements** **[Runnable](http://javarevisited.blogspot.sg/2012/01/difference-thread-vs-runnable-interface.html)** {
**private** **CyclicBarrier**barrier;
**public**Task(**cyclicBarrier**barrier) {
**this**.barrier\= barrier;
}
@**Override**
**public** **void**run() {
**try** {
**System**.out.println(**Thread**.currentThread().getName()+" is waiting on barrier");
barrier.await();
**System**.out.println(**Thread**.currentThread() 。getName()+" 已越过障碍");
} **catch** (**InterruptedException**ex) {
**Logger**.getLogger(CyclicBarrierExample.**class**.getName()).log(**Level**.SEVERE,**null**, ex);
} **catch** (**BrokenBarrierException**ex) {
**Logger**.getLogger(CyclicBarrierExample.**class**.getName() )log(**Level**.SEVERE,**null**, ex);
}
}
}
**public** **static** **void**main(**String**args\[\]) {
*//创建有3方的CyclicBarrier,即。3个线程需要调用 await()*
**final** **CyclicBarrier**cb =**new** **CyclicBarrier**(3,**new** **Runnable**(){
@**Override**
**public** **void**run(){
*//一旦所有线程到达屏障,这个任务将被执行*
**System**.out.println("All parties are arrived at barrier, let play");
})
});
*//启动每个线程*
**Thread**t1 =**new** **Thread**(**new**Task(cb),"Thread 1");
**Thread**t2 =**new** **Thread**(**new**Task(cb),"Thread 2");
**Thread**t3 =**new** **Thread**(**new**Task(cb),"Thread 3");
t1.start();
t2.start();
t3.start();
}
}
**输出:**
**线程** 1在障碍物上等待
线程3在障碍物上等待
**线程** 2在障碍物上等待
所有各方都已到达障碍物,让我们玩吧
**线程** 3已越过障碍物
**线程** 1已越过障碍物
**线程** 2已越过障碍物
何时使用 循环屏障 在Java中使用?例子
鉴于 CyclicBarrier的性质 , 它可以非常方便地实现类似于Java 7的fork-join框架的map-reduce类型的任务,其中一个大任务被分解成小块,为了完成任务,你需要从各个小任务中得到输出。
例如,要计算印度的人口,你可以有4个线程,分别计算北、南、东、西的人口,一旦完成,它们可以互相等待。 当最后一个线程完成他们的任务时,主线程或任何其他线程可以将每个区域的结果相加,并打印总人口。
你可以 在Java中使用 CyclicBarrier 。
- 实现多人游戏,在所有玩家都加入之前,游戏不能开始。
2)通过将其分解为较小的单独任务来执行冗长的计算,一般来说,实现Map reduce技术。
如果你想进一步了解Java中的CyclicBarrier,那么你可以进一步查看 Udemy上的Java中的多线程和并行计算 课程,这是一个学习Java中多线程基础知识的好课程,你可以在Udemy的销售中只花10美元购买。
重要的一点是 循环壁垒 在Java中的重要性
1. 一旦所有的线程到达屏障 ,CyclicBarrier 就可以执行一个完成任务,这可以在创建 CyclicBarrier 时提供 。
2.如果 CyclicBarrier 被初始化为3方,意味着3个线程需要调用await方法来打破障碍。
3.3 . 线程将 在await()上阻塞 ,直到所有各方都到达屏障,另一个线程中断或 await 超时。
4.如果另一个线程中断了正在等待屏障的线程,它将抛出 BrocernBarrierException ,如下所示。
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:172)
at java.util.concurrent.await(CyclicBarrier.java:327)
5.CyclicBarrier.reset()将 屏障 置于初始状态,其他正在等待或尚未到达屏障的线程将以 java.util.concurrent.BrokenBarrierException终止。
以上就是关于什么是 循环壁垒在Java中 何时使用CyclicBarrier 以及如何在Java中使用CyclicBarrier的一个简单例子。我们还看到了 Java中 CountDownLatch 和 CyclicBarrier的区别 ,并了解了在 Java并发代码中 可以使用 CyclicBarrier的 一些 情况 。