参考:http://wangxinchun.iteye.com/blog/1883502
使用场景:它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在屏障点运行一次,(注意:实际上是在最后一个线程中执行的!!!)若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 【···引用jdk中文翻译】
实现依赖:
1、lock 可重入锁 ReentrantLock
2、Condition 条件谓词。
实现思路:就是设置一个计数,每当有线程达到时,计数count-1,Condition.await 进入阻塞, 当count =0,那么可以 signalAll ,让所有线程得以唤醒。 唤醒后立马重置!
package java.util.concurrent;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class CyclicBarrier {
/**
* Each use of the barrier is represented as a generation instance.
* The generation changes whenever the barrier is tripped, or
* is reset. There can be many generations associated with threads
* using the barrier - due to the non-deterministic[非一成不变] way the lock
* may be allocated to waiting threads - but only one of these
* can be active at a time (the one to which {@code count} applies)
* and all the rest are either broken or tripped.
* There need not be an active generation if there has been a break
* but no subsequent reset.
*/
private static class Generation {
boolean broken = false;
}
/*
静态内部类和非静态内部类之间到底有什么不同呢?下面是两者间主要的不同。
(1)内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。
(2)非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。
(3)一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。
*/
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
/* The command to run when tripped */
private final Runnable barrierCommand;//ksgimi 结束后运行的脚本
/** The current generation */
private Generation generation = new Generation(); //ksgimi 注意是static类
/**
* Number of parties still waiting. Counts down from parties to 0
* on each generation. It is reset to parties on each new
* generation or when broken.
*/
private int count;
/**
* Updates state on barrier trip and wakes up everyone.
* Called only while holding lock.
*/
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
/**
* Sets current barrier generation as broken and wakes up everyone.
* Called only while holding lock.
*/
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
/**
* Main barrier code, covering the various policies.
*/
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();//ksgimi 防止command.run()出异常
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);// ksgimi ?
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.[随后的;后来的]
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;//ksgimi 已recycle
if (timed && nanos <= 0L) {//ksgimi 超时
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
/**
* Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and which
* will execute the given barrier action when the barrier is tripped,
* performed by the last thread entering the barrier.
*
* @param parties the number of threads that must invoke {@link #await}
* before the barrier is tripped
* @param barrierAction the command to execute when the barrier is
* tripped, or {@code null} if there is no action
* @throws IllegalArgumentException if {@code parties} is less than 1
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
/**
* Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and
* does not perform a predefined action when the barrier is tripped.
*
* @param parties the number of threads that must invoke {@link #await}
* before the barrier is tripped
* @throws IllegalArgumentException if {@code parties} is less than 1
*/
public CyclicBarrier(int parties) {
this(parties, null);
}
/**
* Returns the number of parties required to trip this barrier.
*
* @return the number of parties required to trip this barrier
*/
public int getParties() {
return parties;
}
/**
* Waits until all {@linkplain #getParties parties} have invoked
* {@code await} on this barrier.
*
* <p>If the current thread is not the last to arrive then it is
* disabled for thread scheduling purposes and lies dormant until
* one of the following things happens:
* <ul>
* <li>The last thread arrives; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* one of the other waiting threads; or
* <li>Some other thread times out while waiting for barrier; or
* <li>Some other thread invokes {@link #reset} on this barrier.
* </ul>
*
* <p>If the current thread:
* <ul>
* <li>has its interrupted status set on entry to this method; or
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
* </ul>
* then {@link InterruptedException} is thrown and the current thread's
* interrupted status is cleared.
*
* <p>If the barrier is {@link #reset} while any thread is waiting,
* or if the barrier {@linkplain #isBroken is broken} when
* {@code await} is invoked, or while any thread is waiting, then
* {@link BrokenBarrierException} is thrown.
*
* <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
* then all other waiting threads will throw
* {@link BrokenBarrierException} and the barrier is placed in the broken
* state.
*
* <p>If the current thread is the last thread to arrive, and a
* non-null barrier action was supplied in the constructor, then the
* current thread runs the action before allowing the other threads to
* continue.
* If an exception occurs during the barrier action then that exception
* will be propagated in the current thread and the barrier is placed in
* the broken state.
*
* @return the arrival index of the current thread, where index
* {@code getParties() - 1} indicates the first
* to arrive and zero indicates the last to arrive
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws BrokenBarrierException if <em>another</em> thread was
* interrupted or timed out while the current thread was
* waiting, or the barrier was reset, or the barrier was
* broken when {@code await} was called, or the barrier
* action (if present) failed due to an exception
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
}
/**
* Queries if this barrier is in a broken state.
*
* @return {@code true} if one or more parties broke out of this
* barrier due to interruption or timeout since
* construction or the last reset, or a barrier action
* failed due to an exception; {@code false} otherwise.
*/
public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
}
/**
* Resets the barrier to its initial state. If any parties are
* currently waiting at the barrier, they will return with a
* {@link BrokenBarrierException}. Note that resets <em>after</em>
* a breakage has occurred for other reasons can be complicated to
* carry out; threads need to re-synchronize in some other way,
* and choose one to perform the reset. It may be preferable to
* instead create a new barrier for subsequent use.
*/
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
/**
* Returns the number of parties currently waiting at the barrier.
* This method is primarily useful for debugging and assertions.
*
* @return the number of parties currently blocked in {@link #await}
*/
public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return parties - count;
} finally {
lock.unlock();
}
}
}
分享到:
相关推荐
Java源码大全是一个珍贵的学习资源,它包含了作者在参加上海杰普培训时积累的重要Java基础知识。这个压缩包可能包括了核心Java(Core Java)的各个方面,如I/O(输入/输出)、多线程(Thread)以及其他关键概念。...
8. **网络编程**:Java提供了Socket和ServerSocket类来支持网络通信。这部分内容可能涉及到客户端和服务器之间的数据交换,以及TCP和UDP协议的差异。 9. **泛型**:泛型是Java 5引入的新特性,用于提供类型安全的...
Java提供了多种线程同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Semaphore、CyclicBarrier等高级并发工具。 2. **并发下载策略**:在FlashGet的实现中,关键在于如何有效地分配和管理...
8. **JVM内部机制**:虽然Java源码不包括JVM本身,但通过阅读和分析使用JVM特性的代码,如内存管理、垃圾回收等,可以增进对JVM的理解。 9. **泛型**:Java泛型提高了代码的类型安全性和重用性。源码可以展示如何...
本资源“java concurrent 精简源码”着重关注Java并发库(java.util.concurrent)的核心概念,包括阻塞队列和线程管理。下面将详细阐述这些知识点。 1. **Java并发库(java.util.concurrent)** Java并发库是Java ...
"140个Java源码实例"是一份珍贵的学习资源,它包含了多个实际编程场景下的代码示例,旨在帮助初学者更好地理解和掌握Java编程。 在学习这140个Java源码实例时,我们可以按照以下主要知识点进行分类和深入学习: 1....
《深入Java虚拟机源码》一书主要涵盖了Java虚拟机(JVM)的内部工作原理,包括类加载机制、内存管理、字节码执行引擎、垃圾收集算法、编译优化等多个核心主题。以下是对这些章节内容的详细阐述: 1. **第3章:类...
Java并发系列之CyclicBarrier源码分析 CyclicBarrier是Java并发系列中的一种同步工具类,用于实现一组线程相互等待。当所有线程都到达某个屏障点后,再进行后续的操作。下面是对CyclicBarrier源码的详细分析。 ...
Java提供了丰富的并发工具和API,如`Thread`类、`ExecutorService`、`Semaphore`、`CountDownLatch`、`CyclicBarrier`等,这些都将在源码中有所体现。 1. **线程与线程安全** Java并发编程的基础是`Thread`类,...
14. **并发工具**:Java并发包提供了多种工具,如CountDownLatch、Semaphore、CyclicBarrier等,用于协调多线程间的操作。 通过这个完整的Java教程示例源码,学习者可以动手实践,加深对每个主题的理解,从而提升...
8. **v2ch11**:可能涵盖Java的GUI(图形用户界面)编程,如Swing和JavaFX,包括组件使用、事件处理和布局管理。这有助于开发交互式的桌面应用程序。 9. **v1ch07**:可能涉及Java的泛型,包括类型参数、通配符和...
Java源码笔记主要涵盖的是Java编程语言的核心概念和高级特性,特别是与网络编程相关的部分。在深入理解Java源码的过程中,我们不仅可以了解到语言的基础结构,还能探索其在网络通信中的应用。下面将对Java源码和网络...
此外,Java的多线程编程也是Azureus实现P2P通信的关键,因此熟悉Thread和Runnable接口,以及并发控制工具如synchronized关键字、Semaphore、CyclicBarrier等是必要的。 2. **BitTorrent协议**:Azureus的核心是...
Java 1.6 引入了并发工具包 `java.util.concurrent`,包含如 Semaphore、CyclicBarrier 和 ExecutorService 等,为多线程编程提供了一组高效、线程安全的工具。 7. **NIO(Non-blocking Input/Output)**: NIO ...
《深入解析ADVANCE_JAVA源码》 ADVANCE_JAVA-源码.rar 是一个压缩包文件,其中包含的源码是针对高级Java编程的学习资源。Java作为一种广泛应用的编程语言,其高级特性对于开发者来说至关重要,这包括但不限于多线程...
深入研究Java多线程和同步的源码,可以帮助理解其底层机制。例如,`Thread`类的内部实现、`synchronized`关键字如何实现内存同步、`ReentrantLock`如何实现可重入和公平性等。你可以通过反编译JDK源码或查看OpenJDK...
"java并发源码分析之实战编程"这个主题深入探讨了Java平台上的并发处理机制,旨在帮助开发者理解并有效地利用这些机制来提高程序性能和可扩展性。在这个专题中,我们将围绕Java并发库、线程管理、锁机制、并发容器...
这里我们关注的是28个常用的Java工具类源码,它们涵盖了数据处理、字符串操作、集合操作等多个方面。了解并深入学习这些工具类的源码,对于提升编程技能、理解Java内部机制以及优化代码性能有着巨大的帮助。 首先,...
【CoreJava源码详解】 CoreJava是Java编程的基础部分,主要涵盖了Java语言的核心特性、类库和编程实践。达内科技作为知名的IT培训机构,提供的这个源码集合可以帮助学习者深入理解Java编程的本质,掌握核心技能。 ...