CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。
若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
示例用法:下面是一个在并行分解设计中使用 barrier 的例子:
class Solver {
final int N;
final float[][] data;
final CyclicBarrier barrier;
class Worker implements Runnable {
int myRow;
Worker(int row) { myRow = row; }
public void run() {
while (!done()) {
processRow(myRow);
try {
barrier.await();
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
}
public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
barrier = new CyclicBarrier(N,
new Runnable() {
public void run() {
mergeRows( );
}
});
for (int i = 0; i < N; ++i)
new Thread(new Worker(i)).start();
waitUntilDone();
}
}
在这个例子中,每个 worker 线程处理矩阵的一行,在处理完所有的行之前,该线程将一直在屏障处等待。
处理完所有的行之后,将执行所提供的 Runnable 屏障操作,并合并这些行。
如果合并者确定已经找到了一个解决方案,那么 done() 将返回 true,所有的 worker 线程都将终止。
如果屏障操作在执行时不依赖于正挂起的线程,则线程组中的任何线程在获得释放时都能执行该操作。
为方便此操作,每次调用 await() 都将返回能到达屏障处的线程的索引。然后,您可以选择哪个线程应该执行屏障操作,例如:
if (barrier.await() == 0) {
// log the completion of this iteration
}对于失败的同步尝试,CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么在该屏障点等待的其他所有线程也将通过 BrokenBarrierException(如果它们几乎同时被中断,则用 InterruptedException)以反常的方式离开。
内存一致性效果:线程中调用 await() 之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次 happen-before 紧跟在从另一个线程中对应 await() 成功返回的操作。
(1)await
public int await() throws InterruptedException, BrokenBarrierException在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
如果当前线程不是将到达的最后一个线程,出于调度目的,将禁用它,且在发生以下情况之一前,该线程将一直处于休眠状态:
最后一个线程到达;或者
其他某个线程中断当前线程;或者
其他某个线程中断另一个等待线程;或者
其他某个线程在等待 barrier 时超时;或者
其他某个线程在此 barrier 上调用 reset()。
如果当前线程:
在进入此方法时已经设置了该线程的中断状态;或者
在等待时被中断
则抛出 InterruptedException,并且清除当前线程的已中断状态。
如果在线程处于等待状态时 barrier 被 reset(),或者在调用 await 时 barrier 被损坏,抑或任意一个线程正处于等待状态,则抛出 BrokenBarrierException 异常。
如果任何线程在等待时被 中断,则其他所有等待线程都将抛出 BrokenBarrierException 异常,并将 barrier 置于损坏状态。
如果当前线程是最后一个将要到达的线程,并且构造方法中提供了一个非空的屏障操作,则在允许其他线程继续运行之前,当前线程将运行该操作。
如果在执行屏障操作过程中发生异常,则该异常将传播到当前线程中,并将 barrier 置于损坏状态。
返回:
到达的当前线程的索引,其中,索引 getParties() - 1 指示将到达的第一个线程,零指示最后一个到达的线程
抛出:
InterruptedException - 如果当前线程在等待时被中断 www.2cto.com
BrokenBarrierException - 如果另一个 线程在当前线程等待时被中断或超时,或者重置了 barrier,或者在调用 await 时 barrier 被损坏,抑或由于异常而导致屏障操作(如果存在)失败。
(2)getNumberWaiting
public int getNumberWaiting()返回当前在屏障处等待的参与者数目。此方法主要用于调试和断言。
返回:
当前阻塞在 await() 中的参与者数目。
应用实例:
package com.itm.thread;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierTest {
public static void main(String[] args) {
final CyclicBarrier cb = new CyclicBarrier(3); // 这个团队中共有3个队员,即需要3个线程
ExecutorService es = Executors.newFixedThreadPool(3); // 在线程池中放入三个线程
for (int i = 0; i < 3; i++) { // 开启三个任务
es.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(new Random().nextInt(5000));
System.out.print(Thread.currentThread().getName()
+ "已到达集合点" + (i + 1) + ",现在共有"
+ (cb.getNumberWaiting() + 1) + "个线程到达");
// 如果有2个线程已经在等待,那么最后一个线程到达后就可以一起开始后面操作
if (cb.getNumberWaiting() + 1 == 3) {
System.out.println(",全部到齐,出发去下一个目标");
} else {
System.out.println(",正在等待");
}
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
es.shutdown();
}
}
运行结果:
pool-1-thread-3已到达集合点1,现在共有1个线程到达,正在等待
pool-1-thread-2已到达集合点1,现在共有2个线程到达,正在等待
pool-1-thread-1已到达集合点1,现在共有3个线程到达,全部到齐,出发去下一个目标
pool-1-thread-3已到达集合点2,现在共有1个线程到达,正在等待
pool-1-thread-1已到达集合点2,现在共有2个线程到达,正在等待
pool-1-thread-2已到达集合点2,现在共有3个线程到达,全部到齐,出发去下一个目标
pool-1-thread-1已到达集合点3,现在共有1个线程到达,正在等待
pool-1-thread-2已到达集合点3,现在共有2个线程到达,正在等待
pool-1-thread-3已到达集合点3,现在共有3个线程到达,全部到齐,出发去下一个目标
pool-1-thread-1已到达集合点4,现在共有1个线程到达,正在等待
pool-1-thread-2已到达集合点4,现在共有2个线程到达,正在等待
pool-1-thread-3已到达集合点4,现在共有3个线程到达,全部到齐,出发去下一个目标
pool-1-thread-2已到达集合点5,现在共有1个线程到达,正在等待
pool-1-thread-3已到达集合点5,现在共有2个线程到达,正在等待
pool-1-thread-1已到达集合点5,现在共有3个线程到达,全部到齐,出发去下一个目标
摘自 jlins_you
相关推荐
16. 执行器服务 ExecutorService 17. 线程池执行者 ThreadPoolExecutor 18. 定时执行者服务 ScheduledExecutorService 19. 使用 ForkJoinPool 进行分叉和合并 20. 锁 Lock 21. 读写锁 ReadWriteLock 22. 原子性布尔 ...
Java 5并发包(`java.util.concurrent`,简称`Concurrent`包)是Java平台中用于多线程编程的重要组成部分,它提供了丰富的并发工具类,极大地简化了在多线程环境下的编程工作。这个包的设计目标是提高并发性能,减少...
JUC提供了丰富的并发原语,如线程池、同步器、并发容器等,极大地简化了多线程编程的复杂性,并提升了程序的性能和可维护性。以下是对JUC库的详细解析: 1. **线程池(ExecutorService)**: - `ExecutorService`...
3. **同步工具类**:Java并发包`java.util.concurrent`中的工具类,如`Semaphore`(信号量)、`CyclicBarrier`(回环栅栏)、`CountDownLatch`(倒计时器)和`FutureTask`(未来任务)等,提供了更灵活的线程同步和...
除了原子量和同步器,JDK并发包还提供了显式锁,如ReentrantLock,它提供了比synchronized更灵活的控制,包括公平锁和非公平锁,以及可中断的锁等待和定时锁等待。 总之,JDK并发包为开发者提供了丰富的工具来处理...
它是实现Java并发包中锁和其他同步器的基础框架,例如ReentrantLock(可重入锁)、Semaphore(信号量)、CountDownLatch(倒计时门闩)、CyclicBarrier(循环栅栏)以及ReentrantReadWriteLock(可重入读写锁)等。...
Java并发包中的某些类如`AtomicInteger`、`ConcurrentHashMap`等是线程安全的,无需额外的同步措施。 2. **Executor框架**:`java.util.concurrent.Executor`是执行任务的核心接口,它定义了运行任务的方法。`...
同时,Java并发包中的CountDownLatch、CyclicBarrier、Semaphore等同步器为线程间协作提供了强大的支持。 除了Java并发包提供的工具之外,理解和使用并发编程的模式同样重要。例如,生产者-消费者模式是多线程编程...
Java提供了多种同步工具,包括`synchronized`关键字、`Lock`接口(如`ReentrantLock`)、`Semaphore`信号量、`CountDownLatch`倒计时器以及`CyclicBarrier`回环栅栏。`synchronized`关键字可以用于方法或代码块,...
同步器是用于协调多个线程之间协作机制的工具,Java并发包中提供了CountDownLatch、Semaphore、Exchanger、CyclicBarrier等同步器,它们可以在复杂的并发场景中提供高效的线程间同步。 在并发编程实践中,还提到了...
2. **Java并发包**: `java.util.concurrent`(JUC)包是Java并发编程的核心,包含各种并发工具类,如`Semaphore`(信号量)、`CountDownLatch`(计数器)、`CyclicBarrier`(回环栅栏)、`ThreadPoolExecutor`...
9. **并发编程**:Java并发包(java.util.concurrent)提供了许多高级并发工具,如CountDownLatch、CyclicBarrier、Semaphore等,用于构建高并发应用。 10. **Spring框架**:作为Java企业级应用的主流框架,Spring...
CountDownLatch 是 Java 并发包中的一个重要组件,它主要用于解决“一个或多个线程等待其他线程完成任务”的问题。CountDownLatch 的核心概念是“计数器”,这个计数器必须由调用 `countDown()` 方法的线程递减,当...
本节主要讲解了Java并发包中线程同步器原理剖析,具体来说是 CountDownLatch 和 CyclicBarrier 的使用和原理剖析。 一、CountDownLatch CountDownLatch 是一个同步工具,它可以让一个线程等待其他线程完成某些操作...
java.util.concurrent(JUC)包包含了一系列高级并发工具,如Semaphore(信号量)、CyclicBarrier(回环屏障)、CountDownLatch(计数器门锁)和Exchanger(交换器),它们提供了更复杂的同步机制。另外,...
4. **并发容器**:Java并发包(java.util.concurrent)提供了一系列优化的并发容器,如ConcurrentHashMap、BlockingQueue、CopyOnWriteArrayList等,这些容器设计巧妙,能够在多线程环境下保持高效性能。 5. **原子...
另外,Java的并发包(java.util.concurrent)提供了丰富的方法和工具,如Semaphore(信号量)、CyclicBarrier(循环屏障)和CountDownLatch(倒计时器)等,帮助开发者更高效地管理同步问题。 在实际应用中,开发者...
此外,Java并发包`java.util.concurrent`提供了丰富的高级并发工具,如`ExecutorService`、`Future`、`Callable`、`Semaphore`、`CyclicBarrier`等。这些工具可以帮助开发者更高效、安全地管理线程,实现线程池、...
Java并发包(`java.util.concurrent`)提供了一系列高级并发工具,如`Semaphore`(信号量)、`CyclicBarrier`(循环屏障)、`CountDownLatch`(倒计时器)和`ExecutorService`等,它们可以帮助开发者更有效地管理线程...