线程间应该怎样协作?
信号量 Semaphore
作用和用途
- 限制某一程序或应用的并发线程数,通过信号量许可证的颁发和回收来控制 执行任务的线程数。
使用
-
初始化信号量 new Semaphore(int permits, boolean fair) permit : 许可证数量,限制并发线程数, fair:等待获取许可证的线程采用什么等待策略(公平、非公平) 一般情况下非公平的策略会对吞吐量有明显的提升。
# 初始化信号量 Semaphore semaphore = new Semaphore(3, false);
-
一个线程通过 acquire() 或 acquireUninterruptibly 请求尝试获取许可证,如果获取不到许可证,那么当前线程就阻塞。
# 尝试获取许可证(可响应中断, 在获取信号量许可证的期间,线程中断了,那么就跳出acquire, 不再阻塞等待获取许可证)
semaphore.acquire()
# 尝试获取许可证 (不响应线程中断)
semaphore.acquireUninterruptibly()
-
执行完后请求 release() 方法,释放信号量许可证。
semaphore.release();
CountDownLatch
主要方法
-
await()
调用了 await() 方法的线程开始 阻塞等待,直至 count 值 变为 0 的时候,才被唤醒继续执行。
-
await(long timeout ,TimeUnit unit)
await() 方法的重载, 可以设定超时时间,当超过了设定的超时时间后,将不再继续等待。
-
countDown()
把 count 值 减去1 ,直至减为0 , 之前阻塞等待的线程会被唤醒。
用法细节
- 主线程等待所有子线程任务执行完毕后,在继续执行主线程自己的任务。、
- 多个线程等待同一个线程的执行信号, 同时开始执行。
- countDownLatch 不能重用,如果一个流程已经完成了倒数,那么不能够重新再执行一次倒数流程。
循环屏障 CyclicBarrier VS CountDownLatch
相同点
- 都能阻塞一个或一组线程, 直至达成某个预设的count 值的条件,才能执行线程任务。
不同点
-
作用对象不同,
CyclicBarrier 等待设定数量的线程都到达屏障位置时(await () 方法调用,计数减去1 ),才能继续执行。 【作用与线程】
CountDownLatch 只需等待 count 计数置为 0 (countDown() 方法调用,计数减去1),就可继续线程任务的执行。 【作用于事件】
-
可重用性不同
CountDownLatch 在计数置为0 线程被唤醒执行任务, 就不可重用了,
CyclicBarrier 是可以重用的,且可以通过reset() 方法重置, 如果重置时已经有线程调用了await() 方法并且开始在屏障处等待, 那么这些线程会抛出BrokenBarrierException 异常。 -
是否有后置执行动作
CyclicBarrier 可以指定 barrierAction
CyclicBarrier(int parties, Runnable barrierAction)
网友评论