并发编程之Tools&CountDownLatch&Semaphore原理与应用
1. Semaphore 是什么?
Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目。
2. 怎么使用 Semaphore?
2.1 构造方法
1 | public Semaphore(int permits) |
2.2 重要方法
其中acquire() 表示阻塞并获取许可 release() 表示释放许可
1 | public void acquire() throws InterruptedException |
2.3 基本使用
需求场景:资源访问,服务限流。
代码示例
1 | import java.util.concurrent.Semaphore; |
从打印结果可以看出,一次只有两个线程执行 acquire(),只有线程进行 release() 方法后 才会有别的线程执行 acquire()。
3. CountDownLatch使用及应用场景
3.1 CountDownLatch是什么?
CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。
例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
3.2 CountDownLatch如何工作?
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
API
1 | CountDownLatch.countDown() |
3.3 CountDownLatch应用场景例子
比如陪媳妇去看病。 医院里边排队的人很多,如果一个人的话,要先看大夫,看完大夫再去排队交钱取药。
现在我们是双核,可以同时做这两个事(多线程)。
假设看大夫花3秒钟,排队交费取药花5秒钟。我们同时搞的话,5秒钟我们就能完成,然后一起回家(回到主线程)。
代码如下:
1 | /*** 看大夫任务 */ |
4. CyclicBarrier
栅栏屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程 到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线 程数量,每个线程调用await方法告CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
API
1 | cyclicBarrier.await(); |
- 应用场景
可以用于多线程计算数据,最后合并计算结果的场景。例如,用一个Excel保存了用户 所有银行流水,每个Sheet保存一个账户近一年的每笔银行流水,现在需要统计用户的日均 银行流水,先用多线程处理每个sheet里的银行流水,都执行完之后,得到每个sheet的日
均银行流水,最后,再用barrierAction用这些线程的计算结果,计算出整个Excel的日 均银行流水。
示例代码:
1 | public class CyclicBarrierTest implements Runnable { |
5. Executors
主要用来创建线程池,代理了线程池的创建,使得你的创建入口参数变得简单
重要方法
- newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作 线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
6.Exchanger
当一个线程运行到exchange()方法时会阻塞,另一个线程运行到exchange()时,二者 交换数据,然后执行后面的程序
应用场景 极少,大家了解即可
1 | public class ExchangerTest { |