Java中的并发工具类
等待多线程完成的CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程完成操作。
假设有如下需要:在一个Excel表有多个sheet数据,每一个线程处理一个sheet的数据。待所有数据处理完毕,主线程发出结束消息。
使用join方法
|
|
使用更加强大的CountDownLatch
|
|
await可以设置超时等待,在主线程超时放弃等待countDown的计数到0
同步屏障CyclicBarrier
让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被拦截的线程才能继续运行。
运行的线程会被阻塞在 barrier.await() 处。
构造函数:
|
|
示例
|
|
CyclicBarrier和CountDownLatch的区别
CountDwonLatch的计数器只能使用一次,而CyclicBarrier的计数器可是使用reset()方法重置。所以CyclicBarrier能处理更为复杂的业务场景。例如,计算发生错误,可以重置计数器,并让线程重新执行一次。
CyclicBarrier还提供以下方法
方法 | 描述 |
---|---|
void reset() | 重置计数器,不是初始值,而是剩余的计数值 |
int getNumberWaiting() | 返回CyclicBarrier阻塞的线程的线程数量 |
boolean isBroken() | 了解阻塞的线程是否被中断 |
控制并发线程数的Semaphore
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
应用场景
Semaphore可以用于做流量控制,特别是公用资源有限的应用场景,比如数据库连接。加入有一个需求,需要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发地读取,但是如果读到内存后,还需要存储都数据库中,而数据库的连接数只有10个,这时我们必须控制只有10个线程同时获取数据库连接保存数据,否则会报错无法获取数据库连接。这个时候,就可以使用Semaphore来做流量控制。
|
|
方法 | 描述 |
---|---|
public Semaphore(int permits) | 最大并发数为permits |
void acquire() | 获取一个许可证, 没有获取到就阻塞 |
void release() | 使用完之后记得归回许可证 |
int availablePermits() | 返回当前可以的许可证 |
int getQueueLength() | 返回正在等待获取许可证的线程数 |
boolean hasQueuedThreads() | 是否有线程正在等待获取许可证 |
线程间交换数据的Exchanger
Exchanger是一个用于线程间协作的工具类,可以用来进行线程间的数据交换。它提供一个同步点,在这个同步点,两个可以交换彼此的数据。如果第一个线程先执行exchange()方法,它会一直等待第二个线程也执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产的数据传递给对方。
运用场景
Exchanger可以用于校对工作。
下面代码展示两个线程一直工作直至取到相同的随机数。
|
|
如果两个线程一直有一个没有执行exchange()方法,则会一直等待,如果担心有特殊情况发生,避免一直等待,可以使用exchange(Object o, long timeout, TimeUnit unit)设置最大等待时长。