考虑这么一个情景:当多个线程运行到某处的时候,需要将所有的线程的计算结果汇总。那如何控制这些线程计算子问题结束后,在汇总的代码处等待其它线程尚未计算完的线程呢?可以考虑使用CountDownLatch和CyclicBarrier。CountDownLatch只能使用一次,CyclicBarrier作为线程集结点 ,却可以循环使用。“cyclic”循环的意思。
当跑的快的线程运行到CyclicBarrier实例的await()方法处时,会停下来等待其它尚未到达的线程,直到所有的线程都到达这个代码点,然后开闸泄水!
写了一个练手的程序,这个程序用到了CyclicBarrier可以循环使用的特点:
package thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierTest {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 5; ++i) {
CBRunnable cb = new CBRunnable(i);
es.submit(cb);
}
es.shutdown();
}
}
class CBRunnable implements Runnable {
private static CyclicBarrier cb = new CyclicBarrier(5);
private int idx;
public CBRunnable(int idx) {
this.idx = idx;
}
@Override
public void run() {
System.out.println("Thread " + idx + " starts.");
try {
Thread.sleep(idx * 1000);
System.out.println("step1 : Thread " + idx + " wake up.");
cb.await(); //第一次被使用
System.out.println("Thread " + idx + " step1 ends. ");
Thread.sleep(idx * 1000);
System.out.println("step2 : Thread " + idx + " wake up.");
cb.await(); //第二次被使用
System.out.println("Thread " + idx + " step2 ends.");
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println("Thread " + idx + " ends.");
}
}
程序运行结果:
Thread 0 starts.
Thread 2 starts.
step1 : Thread 0 wake up.
Thread 4 starts.
Thread 1 starts.
Thread 3 starts.
step1 : Thread 1 wake up.
step1 : Thread 2 wake up.
step1 : Thread 3 wake up.
step1 : Thread 4 wake up.
Thread 4 step1 ends.
Thread 0 step1 ends.
Thread 2 step1 ends.
Thread 3 step1 ends.
Thread 1 step1 ends.
step2 : Thread 0 wake up.
step2 : Thread 1 wake up.
step2 : Thread 2 wake up.
step2 : Thread 3 wake up.
step2 : Thread 4 wake up.
Thread 0 step2 ends.
Thread 4 step2 ends.
Thread 1 step2 ends.
Thread 2 step2 ends.
Thread 3 step2 ends.