19 CountDownLatch和CylicBarrier

CountDownLatch

应用场景:一个线程等待多个线程的场景。

这个应用场景很容易理解,假设有三个线程,分别是A,B,C; C要等待A,B完成后再执行,很容易地思路:A.join(); B.join();  再执行C中的任务。   这种方式也很有局限性,先不说线程多了,要写很多join();当使用线程池时,这种方式就无能为力,因为线程池中的线程不可能join(). 

CountDownLatch作用实际上就是一个计数器,countDown()方法:计数减一; await()方法实现对计数器等于0的等待

demo

CyclicBarrier

应用场景:一组线程之间相互等待。注意CountDownLatch的计数不可重复利用,而CyclicBarrier计数器可以循环利用。一旦计数器减到 0 会自动重置到你设置的初始值,而且会调用回调函数。

await() 来将计数器减 1
以上代码是为了实现此优化过程

此示例有点像生产者-消费者,线程T1和线程T2是生产者,而线程T3是消费者。那么问题就在于T1和T2,与T3的关系了。

T1和T2的代码很容易理解,其中await()使计数减一,当减到0的时候调用回调函数,同时重置为2.也就是保证生产完1个P和1个D再去让T3处理,至于T3处理不处理得完,那是T3的问题。 那么P和D的顺序问题就解决了。那么为什么要把T3放到线程池里,而不直接用回调函数? 原因在于:回调函数是同步的!!如果直接用回调,那么就得等T3执行完,才能再次执行(T1和T2),那就起不到优化的作用了。因此使用另一个线程使同步变成异步。

以上的过程也有一点问题,如果生产过快,T3来不及处理,那么线程池会堆积大量的等待,可能会OOM

你可能感兴趣的:(19 CountDownLatch和CylicBarrier)