CountDownLatch、CyclicBarrier、Semaphore、Exchanger
1. CountDownLatch:等待多线程完成的工作模式,允许一个或多个线程等待其他线程完成操作
2. CyclicBarrier:同步屏障,“循环使用的屏障”,让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达时,所有被屏障拦截的线程才会继续执行
3. Semaphore:信号量,用来控制同时访问特定资源的线程数量,应用场景是:用于做流量控制,特别是公用资源有限的场景,例如:数据库连接,系统承受的用户在线量
4. Exchanger:是一个线程间协作的工具类,用于线程间交换数据
上一篇我写的如何正确使用多线程:https://blog.csdn.net/qq_28261811/article/details/112111435 其中包含的例子,希望使用多线程并发的方式,拆分单个任务并进行最终汇总处理的业务场景。
此业务类似于读取Excel文件时,希望并发读取多个sheet,然后进行数据汇总的场景。
可以使用 CountDownLatch、CyclicBarrier 这两个来处理,new CountDownLatch(10) 通过线程到达计数减1 的方式控制工作流程,当计数器减到0时,说明子任务执行完毕,触发主线程执行后续任务;new CyclicBarrier(10),这里的10意为屏障拦截的线程数量,所有的线程之间互相等待,直到所有的线程都到达(执行cyclicBarrier.await()方法)。
这是他们各自处理相同业务的方式,那么他们的区别在哪呢,CountDownLatch 的计数器只能使用一次,而cyclicBarrier的计数器可以使用reset()方法重置,所以cyclicBarrier可以处理更为复杂的业务场景,例如计算错误,可以进行重置计数器,并让线程重新执行一次;并且cyclicBarrier 还提供了其他的工具方法,例如getNumberWaiting()可以获得当前阻塞的线程数量,isBroken() 用作判断阻塞的线程是否被中断。
可以看出,cyclicBarrier比countDownLatch的应用场景更多,使用时更加灵活。例如:使用countDownLatch 时,如果子任务发生异常,这时候只能抛出全局异常,结束当前业务;而cyclicBarrier可以通过异常触发重试机制,重置计数器,重新执行一次任务。
Semaphore和Exchanger会在下一篇进行使用场景的测试,并详细解答
最近看到过一个问题,大家可以一起来思考一下:如何将一个任务拆分成多个子任务并发进行,当其中一个子任务发生异常失败时,其他任务也快速失败。