本文主要介绍的工具包括:

  • CountDownLatch

  • Semaphore

  • CyclicBarrier

  • Exchanger

CountDownLatch

CountDownLatch可以使一个或多个线程等待一组事件发生。在CountDownLatch内部维护一个计数器(被初始化为一个正整数),表示需要等待事件的数量。countDown()方法减少一个事件数量,await()将等待直到计数器为零的时候,才继续执行await后面的代码。如果计数器不为零,那么await将一直会阻塞等待直到计数器为零,或者阻赛线程中断/超时。

@Test public void test() throws InterruptedException {     // thread number     final int threadNum = Runtime.getRuntime().availableProcessors() + 1;     // start event     final CountDownLatch startEvent = new CountDownLatch(1);     // finish event     final CountDownLatch finishEvent = new CountDownLatch(threadNum);      for (int i = 0; i < threadNum; i++) {         new Thread(new Runnable() {             @Override             public void run() {                 try {                     // await for start                     startEvent.await();                     System.out.println(Thread.currentThread() + " start at : " + System.currentTimeMillis());                     // current thread finish                     finishEvent.countDown();                 } catch (InterruptedException ignore) {                  }             }         }).start();          // sleep 0.5ms         TimeUnit.MILLISECONDS.sleep(500);     }      long startTime = System.currentTimeMillis();      startEvent.countDown();     // wait for all thread finish     finishEvent.await();     System.out.println("total finish cost : " + (System.currentTimeMillis() - startTime) + "ms");  } 

这个例子展示了如何在同一时间启动threadNum个线程,并且这threadNum个线程都完成后,记录执行结果。startEvent.await()将等待直到调用startEvent.countDown()。这是,所有线程在同一时间启动。当每个线程执行完毕的时候,会调用finishEvent.countDown()通知给主线程,finishEvent.await()将等待直到所有子线程都执行完毕。

打印结果:

Thread[Thread-1,5,main] start at : 1359782125125 Thread[Thread-8,5,main] start at : 1359782125125 Thread[Thread-7,5,main] start at : 1359782125125 Thread[Thread-6,5,main] start at : 1359782125125 Thread[Thread-5,5,main] start at : 1359782125125 Thread[Thread-3,5,main] start at : 1359782125125 Thread[Thread-0,5,main] start at : 1359782125125 Thread[Thread-2,5,main] start at : 1359782125125 Thread[Thread-4,5,main] start at : 1359782125125 total finish cost : 1ms 

Semaphore

Semaphore在内部持有一个虚拟的许可组(初始化的时候可以设置虚拟组的数量),当执行某个操作的时候,调用acquire获得许可,在操作执行完成后调用release释放许可。如果没有许可可用,那么acquire方法会一直阻赛直到有许可可用为止,或者执行获取许可的线程终端或阻赛。

Semaphore可以用来控制某种资源的使用数量,或者同时使用特定资源的数量。利用这个特性,可以实现某种资源的资源池或者对容器实加边界。

@Test public void test() throws InterruptedException {      final BoundedList list = new BoundedList<>(5);      new Thread(new Runnable() {         @Override         public void run() {             int index = 0;             while (true) {                 try {                     list.add(index++);                     System.out.println(System.currentTimeMillis() + " add " + index);                 } catch (InterruptedException ignore) {                  }             }         }     }).start();      TimeUnit.SECONDS.sleep(1);      new Thread(new Runnable() {         @Override         public void run() {             int index = 0;             while (true) {                 try {                     list.remove(index++);                     System.out.println(System.currentTimeMillis() + " remove " + index);                     TimeUnit.MILLISECONDS.sleep(500);                 } catch (InterruptedException ignore) {                 }             }         }