如何让一段程序并发的执行,并最终汇总结果?
使用CyclicBarrier 在多个关口处将多个线程执行结果汇总, CountDownLatch 在各线程执行完毕后向总线程汇报结果。
CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。
CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待,而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。
从api上理解就是CountdownLatch有主要配合使用两个方法countDown()和await(),countDown()是做事的线程用的方法,await()是等待事情完成的线程用个方法,这两种线程是可以分开的(下面例子:CountdownLatchTest2),当然也可以是同一组线程;CyclicBarrier只有一个方法await(),指的是做事线程必须大家同时等待,必须是同一组线程的工作。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 各个线程执行完成后,主线程做总结性工作的例子
* @author xuexiaolei
* @version 2017年11月02日
*/
public class CountdownLatchTest2 {
private final static int THREAD_NUM = 10;
public static void main(String[] args) {
CountDownLatch lock = new CountDownLatch(THREAD_NUM);
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < THREAD_NUM; i++) {
exec.submit(new CountdownLatchTask(lock, "Thread-"+i));
}
try {
lock.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("大家都执行完成了,做总结性工作");
exec.shutdown();
}
static class CountdownLatchTask implements Runnable{
private final CountDownLatch lock;
private final String threadName;
CountdownLatchTask(CountDownLatch lock, String threadName) {
this.lock = lock;
this.threadName = threadName;
}
@Override public void run() {
System.out.println(threadName + " 执行完成");
lock.countDown();
}
}
}
CyclicBarrier例子:
import java.util.concurrent.*;
/**
*
* @author xuexiaolei
* @version 2017年11月02日
*/
public class CyclicBarrierTest {
private final static int THREAD_NUM = 10;
public static void main(String[] args) {
CyclicBarrier lock = new CyclicBarrier(THREAD_NUM, new Runnable() {
@Override public void run() {
System.out.println("这阶段大家都执行完成了,我总结一下,然后开始下一阶段");
}
});
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < THREAD_NUM; i++) {
exec.submit(new CountdownLatchTask(lock, "Task-"+i));
}
exec.shutdown();
}
static class CountdownLatchTask implements Runnable{
private final CyclicBarrier lock;
private final String threadName;
CountdownLatchTask(CyclicBarrier lock, String threadName) {
this.lock = lock;
this.threadName = threadName;
}
@Override public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(threadName + " 执行完成");
try {
lock.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}