Java多线程专题-Countdownlatch、CyclicBarrier与Semaphore

这三个类都属于java.util.concurrent包下的,用于保证线程安全,用比较简明的话讲,这三个类的主要功能为:

  • Countdownlatch:指定数量的线程执行完后才能向下执行。
  • CyclicBarrier:指定数量的线程到达屏障之后,一起向下执行
  • Semaphore:只允许指定数量的线程同时执行

具体参照下面的详细介绍

CountDownLatch

CountDownLatch可以实现类似计数器的功能。如果一个线程向下继续执行的条件是需要一定数量的任务完成,每个任务完成时都会通知CountDownLatch对象,如果有任务未完成,当前线程处于阻塞状态,直到指定数量的任务都完成了,才向下继续运行。

public class CountDownLatchDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("等待子线程执行完毕...");
        CountDownLatch countDownLatch = new CountDownLatch(2);
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程," +
                		Thread.currentThread().getName() + "开始执行...");
                countDownLatch.countDown();// 每次减去1
                System.out.println("子线程," + 
                		Thread.currentThread().getName() + "结束执行...");
            }
        }).start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("子线程," + 
                		Thread.currentThread().getName() + "开始执行...");
                countDownLatch.countDown();
                System.out.println("子线程," + 
                		Thread.currentThread().getName() + "结束执行...");
            }
        }).start();

        countDownLatch.await();// 调用当前方法主线程阻塞  countDown结果为0, 阻塞变为运行状态
        System.out.println("两个子线程执行完毕....");
        System.out.println("继续主线程执行..");
    }
}

CyclicBarrier

循环屏障(CyclicBarrier)初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。 

CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 

CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。

class Writer extends Thread {
    private CyclicBarrier cyclicBarrier;
    public Writer(CyclicBarrier cyclicBarrier){
         this.cyclicBarrier=cyclicBarrier;
    }
    @Override
    public void run() {
        System.out.println("线程" + 
                Thread.currentThread().getName() + ",正在写入数据");
        try {
            Thread.sleep(3000);
        } catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println("线程" + 
                Thread.currentThread().getName() + ",写入数据成功.....");
        try {
            cyclicBarrier.await();
        } catch (Exception e) {
        }
        System.out.println("所有线程执行完毕..........");
    }
}

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5);
        for (int i = 0; i < 5; i++) {
            Writer writer = new Writer(cyclicBarrier);
            writer.start();
        }
    }
}

Semaphore

Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:

  • availablePermits函数用来获取当前可用的资源数量
  • wc.acquire(); //申请资源
  • wc.release();// 释放资源
class TestSemaphore extends Thread{
    private Semaphore sp ;
    
    public TestSemaphore(Semaphore sp) {
        this.sp = sp;
    }
    
    @Override
    public void run() {
        String t_name = getName();
        try {
            //System.out.println(t_name + "可用:" + availablePermits);
            sp.acquire();
            System.out.println(t_name + "获取信号锁...");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            sp.release();
            System.out.println(t_name + "释放信号锁...");
        }  
    }
}

public class ThreadDemo3 {
    public static void main(String[] args) {
        Semaphore sp = new Semaphore(3);
        for (int i = 0; i < 10; i++) {
            TestSemaphore ts = new TestSemaphore(sp);
            ts.setName(i + 1 + "");
            ts.start();
        }
    }
}

 

 

 

 

 

 

 

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页