A, CyclicBarrier use
CyclicBarrier literally be understood as a direct thread running barrier, which allows a set of threads of execution to be blocked when a common barrier point, until the last thread of execution to the specified location, you set up a thread of execution will trigger operation; at the same time compared with CyclicBarrier CountDownLatch, it can be reset; here we look CyclicBarrier by using a simple example;
Instantiate an object and pass CyclicBarrier internal thread you want to control;
public static void main(String[] args) { CyclicBarrier cb = new CyclicBarrier(3, new Runnable() { public void run() { System.out.println("所有线程集合"); } }); for (int i = 0; i < 3; i++) { new CyclicBarrierThread(i + "", cb).start(); } }
Counting threaded code, calls to even CyclicBarrier whenever count of the await () method
public class CyclicBarrierThread extends Thread{ private CyclicBarrier barrier; private String name; private int count; public CyclicBarrierThread(String name,CyclicBarrier barrier) { this.name=name; this.barrier=barrier; this.count=0; } public void run() { try { for(int i=0;i<10;i++) { Thread.sleep(100); COUNT ++ ; System.out.println (name + "number of threads ---" + Thread.currentThread () getName ( ) + " start counting:." + COUNT); IF (COUNT% 2 == 0) { / / every even number of times counted during a set barrier.await (); System.out.println (name . + "number of threads ---" + Thread.currentThread () getName ( ) + " collection is completed, continue to count" ); } } } the catch (Exception E) { // the TODO Auto-Generated Block the catch e.printStackTrace (); } } }
View Code Output
2 --- Thread-2 thread start counting: 1 0 Number thread --- Thread-0 starts counting: 1 No. 1 thread --- Thread-1 start counting: 1 No. 2 threads --- Thread-2 starts counting : 2 No. 1 thread --- thread-1 starts counting: 2 0 threads --- thread-0 starts counting: 2 All set of threads 2 threads --- the Thread- 2 collection is completed, continue to count No. 1 thread - -Thread- a collection is completed, continue to count 0 threads --- the Thread- 0 collection is completed, continue to count No. 2 threads --- thread-2 start counting: 3 No. 1 thread --- thread-1 start counting: 3 0 No. thread --- thread-0 starts counting: 3 No. 2 threads --- thread-2 start counting: 4 No. 0 threads --- thread-0 starts counting: 4 No. 1 thread --- thread-1 counted: 4 All set of threads No. 1 thread --- Thread- 1 collection is completed, the count continues No. 2 thread --- the Thread- 2 collection is completed, continue to count 0 threads --- the Thread- 0 collection is completed, continue to count number of threads 0 --- Thread-0 starts counting: 5 2 Number of threads --- Thread-2 counting: 5 1 thread --- thread-1 counted: 5 0 threads --- thread-0 starts counting: 6 No. 1 thread --- thread-1 starts counting: 6 2 threads --- the thread counting -2: 6 All set of threads 2 threads --- the Thread- 2 collection is completed, continue to count 0 threads --- the Thread- 0 collection is completed, continue to count No. 1 thread --- the Thread- a collection is completed, continued count number of threads 0 --- thread-0 starts counting: 7 No. 1 thread --- thread-1 counted: 7 No. 2 threads --- thread-2 start counting: 7 No. 1 thread --- thread-1 starts count: 8 0 threads --- thread-0 starts counting: 8 No. 2 threads --- Thread-2 start counting: 8 All set of threads 2 threads --- the Thread- 2 collection is completed, continue to count 0 threads --- the Thread- 0 set complete, continue to count No. 1 thread --- the Thread- a collection is completed, continue to count number of threads 0 --- thread-0 starts counting: 9 No. 1 thread starts counting --- thread-1: 9 No. 2 threads --- thread-2 start counting: 9 No. 1 thread --- thread-1 start counting: 10 0 of the thread --- thread-0 starts counting: 10 No. 2 threads --- thread-2 starts counting: 10 All set of threads 1 No. thread --- the Thread- . 1 collection is completed, continue to count No. 2 threads --- the Thread- 2 collection is completed, continue to count number of threads 0 --- thread-0 collection is completed, continue counting
You can see by the output, counting each thread count to use CyclicBarrier even times when the await () method, the thread will enter the state block waiting until the last thread reaches the barrier point, you define triggers a thread of execution, and the CyclicBarrier the await () method can be used repeatedly.
Two, CyclicBarrier source code analysis
Here we are on the inside of the CyclicBarrier source implementation of some analysis and summary
1, CyclicBarrier construction
First look at the constructor of CyclicBarrier
public a CyclicBarrier ( int parties, the Runnable barrierAction) { IF (parties <= 0) the throw new new an IllegalArgumentException (); // knockdown number of threads the this .parties = parties; // for counting count values, each one thread to execution a barrier point, will be decremented. 1 the this .count = parties; // interceptor defined thread the this .barrierCommand = barrierAction; }
CyclicBarrier constructor was simply receiving a thread of execution you want to block and the number of threads defined.
2, await method
public int await() throws InterruptedException, BrokenBarrierException { try { return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } }
We look at specific implementation methods to achieve dowait
Private int dowait ( Boolean Timed, Long of nanos) throws InterruptedException, a BrokenBarrierException, a TimeoutException { // Get reentrant lock Final of ReentrantLock = Lock the this .lock; // lock Lock.lock (); the try { // a CyclicBarrier defined internally a class Generation Final Generation G = Generation; // Analyzing Generation of a broken state IF (g.broken) the throw new new a BrokenBarrierException (); // if the thread is interrupted IF (Thread.interrupted ()) { // Generation is broken is set to true, count value is reset, and wake up all threads breakBarrier (); the throw new new InterruptedException (); } // COUNT value minus a int index = - COUNT ; IF (index == 0) { // If conunt is 0, indicating the last thread to the Great barrier Boolean ranAction = to false ; the try { final the Runnable Command = barrierCommand; IF ! (Command = null ) command.run (); // execute your incoming thread ranAction = to true ; NextGeneration (); // wake up all the blocked thread, at the same time to reset the count value and Generation return 0 ; } a finally { IF (! ranAction) // intercepting the thread is not normally performed, wake up all the threads, while the count value is reset, the broken Generation set to true breakBarrier (); } } // Loop an until TRIPPED, broken, interrupted, or Timed OUT for (;;) { the try{ // if timeout set obstruction IF (! the Timed) // release the current lock trip.await (); // false representation is not provided, has been blocking the else IF (nanos> 0L ) nanos = trip.awaitNanos (nanos); // to true to set the blocking timeout } the catch (InterruptedException IE) { IF (G Generation == &&! g.broken) { breakBarrier (); the throw IE; } the 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; if (timed && nanos <= 0L) { breakBarrier(); throw new TimeoutException(); } } } The finally { // release lock lock.unlock (); } }
Dowait implementation flow method is very clear, and the count value by the Condition interface ReentrantLock cooperate with each other, provides the following functions:
1, when the need to intercept the thread reaches the barrier point invoked await get ReentrantLock lock to ensure thread-safe;
2, check the count value is 0, it is determined whether the last thread to reach the barrier, and if so execution required to trigger a thread of execution, call the Condition of signalAll method wakes up all the blocked thread, and resets the count value and the Generation category, safeguard CyclicBarrier available repeated;
3, if not the last thread, then await the call Condition method according to the parameters passed to release the lock and enter the resource block waiting until they were awakened;
3, reset method
It can be used to reset the active state CyclicBarrier
public void reset() { final ReentrantLock lock = this.lock; lock.lock(); try { //generation.broken设置为true,唤醒所有线程,count值重置 breakBarrier(); nextGeneration(); } finally { lock.unlock(); } } private void nextGeneration() { // signal completion of last generation trip.signalAll(); // set up next generation count = parties; generation = new Generation(); } private void breakBarrier() { generation.broken = true; count = parties; trip.signalAll(); }
breakBarrier () and nextGeneration (), the main difference between these two methods is that the former will generation.broken set to true, it means that if you call the reset method active reset state CyclicBarrier class, class CyclicBarrier current thread synchronization is being used It will be woken up or throw an exception;
4、getNumberWaiting方法
public int getNumberWaiting() { final ReentrantLock lock = this.lock; lock.lock(); try { return parties - count; } finally { lock.unlock(); } }
Obviously getNumberWaiting method to get the current number of threads have been running to shield the point of waiting and blocked;
Third, the summary
Through the above analysis we can see the realization of the principle CyclicBarrier still comparatively simple and clear, mainly based on the combination of the counter ReentrantLock to synchronize multiple threads of control. The above is achieved with the use of analysis of internal CyclicBarrier classes, which are subject to inadequate and not the right place also pointed out that hope and generosity.
Focus on micro-channel public number to see more technical articles.