CountDownLatch的使用
CountDownLatch是通过“共享锁”实现的。在创建CountDownLatch时,会传递一个int类型参数count,该参数是“锁计数器”的初始状态,表示该“共享锁”最多能被count个线程同时获取。当某线程调用该CountDownLatch对象的await()方法时,该线程会等待“共享锁”可用时,才能获取“共享锁”进而继续运行。而“共享锁”可用的条件,就是“锁计数器”的值为0!而“锁计数器”的初始值为count,每当一个线程调用该CountDownLatch对象的countDown()方法时,才将“锁计数器”-1;通过这种方式,必须有count个线程调用countDown()之后,“锁计数器”才为0,而前面提到的等待线程才能继续运行!
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; public class CountDownLatchTest { private static int LATCH_SIZE = 5; private static CountDownLatch doneSignal; public static void main(String[] args) { try { doneSignal = new CountDownLatch(LATCH_SIZE); // 新建5个任务 for(int i=0; i<LATCH_SIZE; i++) new InnerThread().start(); System.out.println("main await begin."); // "主线程"等待线程池中5个任务的完成 doneSignal.await(); System.out.println("main await finished."); } catch (InterruptedException e) { e.printStackTrace(); } } static class InnerThread extends Thread{ public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " sleep 1000ms."); // 将CountDownLatch的数值减1 doneSignal.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
CyclicBarrier的使用
注意比较CountDownLatch和CyclicBarrier:
(01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
(02) CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
示例一:
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.BrokenBarrierException; public class CyclicBarrierTest1 { private static int SIZE = 5; private static CyclicBarrier cb; public static void main(String[] args) { cb = new CyclicBarrier(SIZE); // 新建5个任务 for(int i=0; i<SIZE; i++) new InnerThread().start(); } static class InnerThread extends Thread{ public void run() { try { System.out.println(Thread.currentThread().getName() + " wait for CyclicBarrier."); // 将cb的参与者数量加1 cb.await(); // cb的参与者数量等于5时,才继续往后执行 System.out.println(Thread.currentThread().getName() + " continued."); } catch (BrokenBarrierException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
结果说明:主线程中新建了5个线程,所有的这些线程都调用cb.await()等待。所有这些线程一直等待,直到cb中所有线程都达到barrier时,这些线程才继续运行!
示例二:
新建5个线程,当这5个线程达到一定的条件时,执行CyclicBarrier构造函数中的Runnable的指定任务。
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.BrokenBarrierException; public class CyclicBarrierTest2 { private static int SIZE = 5; private static CyclicBarrier cb; public static void main(String[] args) { cb = new CyclicBarrier(SIZE, new Runnable () { public void run() { System.out.println("CyclicBarrier's parties is: "+ cb.getParties()); } }); // 新建5个任务 for(int i=0; i<SIZE; i++) new InnerThread().start(); } static class InnerThread extends Thread{ public void run() { try { System.out.println(Thread.currentThread().getName() + " wait for CyclicBarrier."); // 将cb的参与者数量加1 cb.await(); // cb的参与者数量等于5时,才继续往后执行 System.out.println(Thread.currentThread().getName() + " continued."); } catch (BrokenBarrierException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行结果: Thread-1 wait for CyclicBarrier. Thread-2 wait for CyclicBarrier. Thread-3 wait for CyclicBarrier. Thread-4 wait for CyclicBarrier. Thread-0 wait for CyclicBarrier. CyclicBarrier's parties is: 5 Thread-0 continued. Thread-4 continued. Thread-2 continued. Thread-3 continued. Thread-1 continued.
结果说明:主线程中新建了5个线程,所有的这些线程都调用cb.await()等待。所有这些线程一直等待,直到cb中所有线程都达到barrier时,执行新建cb时注册的Runnable任务。