考虑这么一个情景:当多个线程运行到某处的时候,需要将所有的线程的计算结果汇总。那如何控制这些线程计算子问题结束后,在汇总的代码处等待其它线程尚未计算完的线程呢?可以考虑使用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.