Java 并发工具类

CountDownLatch 类

这个类使一个线程等待其他线程各自执行完毕后再执行。是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

  • CountDownLatch(int count):构造一个用给定计数初始化的 CountDownLatch。

  • void await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。

  • boolean await(long timeout, TimeUnit unit):使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。

  • void countDown():递减锁存器的计数,如果计数到达零,则释放所有等待的线程。

  • long getCount():返回当前计数。

  • String toString():返回标识此锁存器及其状态的字符串。

    示例
    public class CountDownLatchDemo { private final static int threadCount = 200; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { test(threadNum); } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } }); } countDownLatch.await(); System.out.println("==>所有程序员完成任务,项目顺利上线!"); exec.shutdown(); } private static void test(int threadNum) throws Exception { Thread.sleep(100); System.out.println(String.format("程序员[%d]完成任务。。。", threadNum)); Thread.sleep(100); } }

CyclicBarrier 类

CyclicBarrier 的作用就是会让所有线程都等待完成后才会继续下一步行动,可以用于多线程计算数据,最后合并计算结果的场景。

  • CyclicBarrier(int parties):parties 是参与线程的个数。
  • CyclicBarrier(int parties, Runnable barrierAction): barrierAction参数是指最后一个到达线程要做的任务。
  • int await():线程调用 await() 表示自己已经到达栅栏,返回当前线程的到达索引,其中 parties - 1表示第一个到达,0表示最后一个到达。
  • int await(long timeout, TimeUnit unit):timeout 参数表示等待屏障的时间,unit 超时参数的时间单位
CyclicBarrier 示例
public class CyclicBarrierDemo { public static void main(String[] args) throws InterruptedException { CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> { System.out.println("回调>>" + Thread.currentThread().getName()); System.out.println("回调>>线程组执行结束"); System.out.println("==>各个子线程执行结束。。。。"); }); for (int i = 0; i < 5; i++) { new Thread(new readNum(i, cyclicBarrier)).start(); } System.out.println("==>主线程执行结束。。。。"); } static class readNum implements Runnable { private int id; private CyclicBarrier cyc; public readNum(int id, CyclicBarrier cyc) { this.id = id; this.cyc = cyc; } @Override public void run() { synchronized (this) { System.out.println("id:" + id + "," + Thread.currentThread().getName()); try { System.out.println("线程组任务" + id + "结束,其他任务继续"); cyc.await(); // 注意跟CountDownLatch不同,这里在子线程await } catch (Exception e) { e.printStackTrace(); } } } } }

CyclicBarrier 与 CountDownLatch 区别

CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的。CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。

CountDownLatchCyclicBarrier
减计数方式加计数方式
计算为0时释放所有等待的线程计数达到指定值时释放所有等待线程
计数为0时,无法重置计数达到指定值时,计数置为0重新开始
调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞
不可重复利用可重复利用

Semaphore 类

通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。通常用于那些资源有明确访问数量限制的场景,常用于限流 。

  • acquire() :获取一个令牌,在获取到令牌、或者被其他线程调用中断之前线程一直处于阻塞状态。
  • acquire(int permits) :获取一个令牌,在获取到令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状态。
  • acquireUninterruptibly() :获取一个令牌,在获取到令牌之前线程一直处于阻塞状态(忽略中断)。
  • tryAcquire():尝试获得令牌,返回获取令牌成功或失败,不阻塞线程。
  • tryAcquire(long timeout, TimeUnit unit):尝试获得令牌,在超时时间内循环尝试获取,直到尝试获取成功或超时返回,不阻塞线程。
  • release():释放一个令牌,唤醒一个获取令牌不成功的阻塞线程。
  • hasQueuedThreads():等待队列里是否还存在等待线程。
  • getQueueLength():获取等待队列里阻塞的线程数。
  • drainPermits():清空令牌把可用令牌数置为0,返回清空令牌的数量。
  • availablePermits():返回可用的令牌数量。
示例
public class SemaphoreDemo { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(5); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { semaphore.acquire(5); // 获取全部许可,退化成串行执行 test(threadNum); semaphore.release(5); // 释放多个许可 } catch (Exception e) { e.printStackTrace(); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { System.out.println("id:" + threadNum + "," + Thread.currentThread().getName()); Thread.sleep(1000); } }

__EOF__

本文作者Justin
本文链接https://www.cnblogs.com/justinxiao/p/17257369.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   justin_xiao  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示