Article Directory
- Principle 1 Introduction
- 2 CountDownLatch relatively simple and CyclicBarrier
- 3 specific use
- 3.1 demo1 --- awit not passed in time, after a specified number of threads to reach the barrier point, and then together to seize the run (cycle interception)
- 3.2 demo2 --- await incoming time t, in front of the thread reaches the barrier at this point and wait, after more than time t thrown across the barrier continues to run
- Some information for each thread running in front after 3.3 demo3 --- use barrierAction reach statistical barrier
Source Address: https://github.com/nieandsun/concurrent-study.git
Principle 1 Introduction
CyclicBarrier, Chinese translation is 循环屏障
the meaning of its name we can at least know two things:
- It can be recycled
- It is a barrier
1.1 CyclicBarrier principle barrier
1.1.1 await null reference
The principle is as follows
- (1) For example, we make CyclicBarrier intercepted three threads (Using the default constructor CyclicBarrier (int parties)), Three threads may be blocked at the same time open, it may not simultaneously turned on, as shown below:
- (2) If the threads 1 and 3 have reached the thread await point (or a barrier point) of each set, but not to the thread 2, they will wait for the thread 2, as shown below:
- (3/1) until the thread 2 also await the arrival point, and then again three threads to run simultaneously seize
- (3/2) CyclicBarrier fact that there are more cattle, it can not only select the number intercepted threads, you can also add a barrierAction (Call the constructor CyclicBarrier (int parties, Runnable barrierAction)). And after the execution timing of this is the thread barrierAction await 1,2,3 have reached the point, that we here can do a lot of interesting things. If the barrierAction, FIG above can be changed following:
When the time passed parameters 1.1.2 await
Drawing here is not, in fact, the CyclicBarrier await method can also pass a time, for example, thread 2 await incoming waiting time of 2 seconds, two seconds after the other thread if not reached await point, it himself first run, and throws an exception. .
The 1.2 CyclicBarrier cycle What does it mean
1.1 is really just talked about the principle CyclicBarrier barrier, but why it is called the circulation barrier it? ? ?
In fact, this is, who saw the underlying source CountDownLatch know whether or CyclicBarrier they control the number of threads in fact depend on a state变量
.
- For example, I was in CountDownLatch specifies the initial state of the number 5, then once countDown, my state decreased by one, until the state was reduced to 0, await automatically release - "But in this state in CountDownLatch Once initialized, you can only reduce, reuse can not be re-used.
- But if I was in CyclicBarrier also specify the initial state of the number 5, for example, I have 10 threads, it will first be blocked for the first five thread -> When they have reached the point await -> Run seize; then you do not need the number manually reset state, a CyclicBarrier after five threads will automatically perform the same operation
这就是所谓的循环的意思
.
2 CountDownLatch relatively simple and CyclicBarrier
Read my last article, " [Concurrent Programming] - CountDownLatch Principle Introduction + to use " 2.3 Summary of look here, will certainly feel CyclicBarrier and achieve CountDownLatch of 发令枪
usage like ah.
In fact, really like, but there are some differences:
- First, CountDownLatch actually made a thread to block other threads, so that other threads to achieve synchronization at a certain point; and CyclicBarrier is
thus blocked by their own individual worker himself calls await, until all worker threads reaches the specified barrier, then everyone down together go. - Secondly, CountDownLatch counter (state) can only be used once, and CyclicBarrier counter can be used repeatedly.
- There, CyclicBarrier of barrierAction actually provides more operational space for us
- Finally, the use of terms
- I CyclicBarrier equivalent to the number specified state is 3, that is, after three threads to reach the barrier point, three threads together through this barrier continues to point to seize the run;
- And I CountDownLatch 3 specifies the number of state, I do not care you are a few threads, you just give me countDown three times, you can cross the barrier point I had set up.
3 specific use
3.1 demo1 - awit not passed in time, after a specified number of threads to reach the barrier point, and then together to seize the run (cycle interception)
- code
package com.nrsc.ch2.juctools;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class CyclicBarrierDemo1 {
private final static int threadCount = 6;
static CyclicBarrier barrier = new CyclicBarrier(2);
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < threadCount; i++) {
final int threadNum = i;
//这里故意让后续线程晚一秒开启
Thread.sleep(1000);
exec.execute(() -> test(threadNum));
}
exec.shutdown();
}
private static void test(int threadNum) {
try {
log.info("线程{}已经准备就绪!", threadNum);
barrier.await();
} catch (InterruptedException e) {
log.error("InterruptedException", e);
} catch (BrokenBarrierException e) {
log.error("BrokenBarrierException", e);
}
log.info("线程{}继续运行!", threadNum);
}
}
- Test Results:
3.2 demo2 - await incoming time t, in front of the thread reaches the barrier at this point and wait, after more than time t thrown across the barrier continues to run
package com.nrsc.ch2.juctools;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class CyclicBarrierDemo2 {
private final static int threadCount = 2;
static CyclicBarrier barrier = new CyclicBarrier(2);
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < threadCount; i++) {
final int threadNum = i;
//这里故意让后续线程晚一秒开启
Thread.sleep(2000);
exec.execute(() -> test(threadNum));
}
exec.shutdown();
}
private static void test(int threadNum) {
try {
log.info("线程{}已经准备就绪!", threadNum);
barrier.await(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("InterruptedException", e);
} catch (BrokenBarrierException e) {
log.error("BrokenBarrierException", e);
} catch (TimeoutException e) {
log.error("TimeoutException", e);
}
log.info("线程{}继续运行!", threadNum);
}
}
- Test Results
Some information for each thread running in front after use barrierAction reach statistical barrier - 3.3 demo3
- code
package com.nrsc.ch2.juctools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;
@Slf4j
public class CyclicBarrierDemo3 {
private final static int threadCount = 5;
private static Map<String, Integer> concurrentHashMap = new ConcurrentHashMap();
static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
MapUtils.verbosePrint(System.out, "前几个线程准备的数据", concurrentHashMap);
});
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < threadCount; i++) {
final int threadNum = i;
//这里故意让后续线程晚一秒开启
Thread.sleep(1000);
exec.execute(() -> test(threadNum));
}
exec.shutdown();
}
private static void test(int threadNum) {
try {
//模拟进行部分准备工作,并将准备的结果放入到Map容器
int random = new Random().nextInt(10);
log.info("线程{}准备的数据-{}",Thread.currentThread().getName(),random);
concurrentHashMap.put(Thread.currentThread().getName(), random);
log.info("线程{}已经准备就绪!", threadNum);
barrier.await();
} catch (InterruptedException e) {
log.error("InterruptedException", e);
} catch (BrokenBarrierException e) {
log.error("BrokenBarrierException", e);
}
log.info("线程{}继续运行!", threadNum);
}
}
- Test Results