什么是Java中的CyclicBarrier实例?教程实例

247 阅读5分钟

在Java中什么是 循环壁垒

Java中的 CyclicBarrier 是JDK 5中引入的一个同步器 , 与其他并发工具如Counting SemaphoreBlockingQueueConcurrentHashMap 等一起 放在 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 。

  1. 实现多人游戏,在所有玩家都加入之前,游戏不能开始。

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的 一些 情况 。