首页 > 其他分享 >CyclicBarrier、CountDownLatch、Semaphore 的用法

CyclicBarrier、CountDownLatch、Semaphore 的用法

时间:2024-07-01 15:28:48浏览次数:3  
标签:Thread int Semaphore 线程 CountDownLatch CyclicBarrier public

CyclicBarrier、CountDownLatch、Semaphore的用法

1.CountDownLatch(程序计数器)

CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。

final CountDownLatch latch = new CountDownLatch(2);
new Thread(){
    public void run(){
        System.out.println("子线程"+Thread.currentThread().getName+"正在执行");
        Thread.sleep(3000);
        System.out.println("子线程"+Thread.currentThread().getName+"执行完毕");
        latch.countDown();
    };
}.start();
new Thread(){
    public void run(){
        System.out.println("子线程"+Thread.currentThread().getName+"正在执行");
        Thread.sleep(3000);
        System.out.println("子线程"+Thread.currentThread().getName+"执行完毕");
        latch.countDown();
    };
}.start();
System.out.println("等待2个子线程执行完毕...");
latch.await();
System.out.println("2个子线程已经执行完毕");
System.out.println("继续执行主线程");

2.CyclicBarrier(回环栅栏-等待至barrier状态再全部同时执行)

字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。

CyclicBarrier中最重要的方法就是await方法,它有2个重载版本:

  1. public int await():用来挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
  2. public int await(long timeout,TimeUnit unit):让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务。

具体使用如下,另外CyclicBarrier是可以重用的。

  public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier = new CyclicBarrier(N);
        for (int i = 0; i < N; i++) {
            new Writer(barrier).start();
        }
    }
    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier barrier){
            this.cyclicBarrier = barrier;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(5000);// 以睡眠来模拟线程需要预定写入数据的操作
                System.out.println("线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入完毕");
                cyclicBarrier.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }catch (BrokenBarrierException e){
                e.printStackTrace();
            }
            System.out.println("所有线程写入完毕,继续处理其他任务,比如数据操作");
        }
    }

3.Semaphore(信号量-控制同时访问的线程个数)

Semaphore翻译成字面意思为信号量,Semaphore可以控制同时访问的线程个数,通过acquire()获取一个许可,如果没有就等待,而release()释放一个许可。

Semaphore类中比较重要的几个方法:

  1. public void acquire():用来获取一个许可,若无许可可能获得,则会一直等待,直到获得许可。
  2. public void acquire(int permints):获取permits个许可。
  3. public void release():释放徐可。注意,在释放许可之前,必须先获得许可。
  4. public void release(int permits):释放permits个许可。

上面4个方法都会被阻塞,如果想立刻得到执行结果,可以使用下面几个方法:

  1. public boolean tryAcquire():尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回false。
  2. public boolean tryAcquire(long timeout ,TimeUnit unit ):尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false。
  3. public boolean tryAcquire(int permits):尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回false。
  4. public boolean tryAcquire(int permits ,long timeout ,TimeUnit unit):尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false。
  5. 还可以通过availablePermits()方法得到可用的许可数目。

例子:若一个工厂有5台机器,但是有8个工人,一台机器同时只能被一个工人使用,只有使用完了,其他工人才能继续使用。那么我们就可以通过Semaphore来实现:

public static void main(String[] args) {
    int N = 8;
    Semaphore semaphore = new Semaphore(5);
    for (int i = 0; i < N; i++) {
        new Worker(i,semaphore).start();
    }
}
static class Worker extends Thread{
    private int num;
    private Semaphore semaphore;
    public Worker(int num,Semaphore semaphore){
        this.num = num;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            System.out.println("工人"+this.num+"占用一个机器在生产");
            Thread.sleep(2000);
            System.out.println("工人"+this.num+"释放机器");
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同;CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。
  • Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。

标签:Thread,int,Semaphore,线程,CountDownLatch,CyclicBarrier,public
From: https://blog.csdn.net/m0_73770897/article/details/140102291

相关文章

  • 深探Java线程池协同神器——CountDownLatch的源码奥秘与实战应用
    1.概述CountDownLatch,作为Java并发包java.util.concurrent下的重要一员,其设计理念在于提供一个线程同步工具,允许一个或多个线程等待其他线程完成操作后再继续执行。在工程师的眼中,它不仅是多线程编程中的一把利器,更是实现线程间高效协同的关键所在。2.源码分析构造函......
  • Go - semaphore
             packagemainimport("context""fmt""os""strconv""time""golang.org/x/sync/semaphore")funcworker(nint)int{square:=n*n......
  • java 常用的辅助类:CountDownLatch,CyclicBarrier,Semaphore
    java常用的辅助类:1.CountDownLatch减法计数器2.CyclicBarrier加法计数器3.Semaphore同一时刻只允许固定(3)个线程执行,完成后另外固定(3)个线程再继续执行1.CountDownLatch:减法计数器.等待所有的执行完成CountDownLatchcountDownLatch=newCountDownLatch(5);//减法计数......
  • CyclicBarrier 使用
    CyclicBarrier同步屏障和CountDownLatch类似可循环使用的屏障,一组线程到达屏障时被阻塞,直到最后一个线程到达时,屏障才开门,所有被拦截的线程继续执行。例如:渣男贾冰,要和3个女生,按照顺序挨个约会:第一个是娜扎,第二个是热巴,第三个是柳岩第一个娜扎先和贾冰约会第二个热巴可以在......
  • CountDownLatch 应用场景
    CountDownLatch倒计数器,是多线程并发时使用的类。主要有2个应用场景:协调子线程结束和子线程开始场景1:协调子线程结束,等待所有子线程结束countDown()执行多次-》await()执行一次例如:组织4个人开会,所有人员都到齐就开始publicclassCountDownLatchTest1{publicst......
  • Java:实现使用CountDownLatch实现线程同步(附完整源码)
    Java:实现使用CountDownLatch实现线程同步我可以帮你实现使用CountDownLatch实现线程同步的Java代码。以下是一个简单的示例:​importjava.util.concurrent.CountDownLatch;​publicclassThreadSyncExample{publicstaticvoidmain(String[]args)t......
  • 信号量(Semaphore),事件Event(了解),队列补充,进程池和线程池(重点),协程理论,Greenlet,Gevent模
    Ⅰ信号量(Semaphore)【一】什么是信号量信号量Semahpore(同线程一样)互斥锁:允许在同一时刻只能有一个线程或进程同资源进行修改信号量:允许指定数量的进程或线程对资源进行修改【二】例子比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去......
  • lock与SemaphoreSlim的区别与应用
    在多线程编程中,线程同步是确保数据一致性和避免竞争条件的重要手段。本文将深入探讨lock(object)和SemaphoreSlim这两种常用的同步机制,详细分析它们的区别、适用场景以及如何在实际开发中选择合适的同步工具。一、lock(object)(或Monitor)1.单线程访问:lock关键字用于确保......
  • 【.NET深呼吸】线程信号量(Semaphore)
    Semaphore类可以控制某个资源允许访问的线程数,Semaphore有命名式的,也有不命名的;如果不考虑跨进程工作,一般在代码中使用不命名方式即可。信号量有点类似于等待句柄,某个线程如果调用了WaitOne方法,这个线程就会暂停,并且等待有可用的信号量时才会继续执行;某个线程调用Release方法,就......
  • JUC框架(Semaphore、CountDownLatch、CyclicBarrier)
    文章目录Semaphore(信号量)Semaphore介绍Semaphore基本概念Semaphore使用场景Semaphore示例CountDownLatch(计数器/闭锁)CountDownLatch介绍CountDownLatch基本概念CountDownLatch使用场景CountDownLatch基本方法CountDownLatch示例CyclicBarrier(循环栅栏)Cyclic......