多线程之CountDownLatch,CyclicBarrier,Semaphore的简单应用

本文深入解析了CountDownLatch、CyclicBarrier和Semaphore三种并发控制工具的原理与应用。CountDownLatch用于等待一组线程完成任务;CyclicBarrier使多个线程在到达某个点时同步;Semaphore则控制同时访问共享资源的线程数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

countDownLatch:

countDownLatch可以实现等待指定数量的线程执行完毕后在执行此线程

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

实例:等待三个学员都准备完毕后,教练才开始训练(三个学员线程都运行到一个位置后,执行教练线程)
/***
     * 等待三个学员准备完毕后,教练开始训练
     */
	private CountDownLatch countDownLatch = new CountDownLatch(3);

    public void Athlete(){
            System.out.println(Thread.currentThread().getName()+"准备完毕");
            countDownLatch.countDown();  //线程数减一  减到0就会唤醒等待其他线程执行的线程
    }

    public void coach(){
            try {
                countDownLatch.await();  //等待其他线程执行后在执行方法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"准备训练");
    }


    public static void main(String[] args) {
        Athletes athletes = new Athletes();
        new Thread(new Runnable() {
            @Override
            public void run() {
                athletes.coach();
            }
        },"教练").start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                athletes.Athlete();
            }
        },"刘翔").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                athletes.Athlete();
            }
        },"姚明").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                athletes.Athlete();
            }
        },"孙杨").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                athletes.Athlete();
            }
        },"哈哈").start();

    }
    //执行结果
    刘翔准备完毕
    姚明准备完毕
    哈哈准备完毕
    教练准备训练
    孙杨准备完毕

CyclicBarrier

CyclicBarrier可以实现等待所有线程都准备好之后,再一起执行

实现原理:计数器递增,提供reset功能,可以多次使用实现原理:计数器递增,提供reset功能,可以多次使用

实例:所有运动员准备好之后,一起出发(等待所有线程都运行到这个位置后,再同时执行)
/***
 * 三个运动员准备后 同时出发
 */
public class CyclicBarrierDemo {

    CyclicBarrier cyclicBarrier = new CyclicBarrier(3);

    public void demo(){
        try {
            System.out.println(Thread.currentThread().getName()+"正在准备");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()+"出发");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        CyclicBarrierDemo cyclicBarrierDemo = new CyclicBarrierDemo();
        new Thread(new Runnable() {
            @Override
            public void run() {
                cyclicBarrierDemo.demo();
            }
        },"运动员一").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                cyclicBarrierDemo.demo();
            }
        },"运动员二").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                cyclicBarrierDemo.demo();
            }
        },"运动员三").start();
    }
}

    //执行结果
    运动员一正在准备
    运动员二正在准备
    运动员三正在准备
    运动员三出发
    运动员一出发
    运动员二出发

Semaphore

信号量:
Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。
Semaphore(int permits):构造方法,创建具有给定许可数的计数信号量并设置为非公平信号量。

Semaphore类所提供的的方法(红色为重要常用方法)
  1. Semaphore(int permits,boolean fair):构造方法,当fair等于true时,创建具有给定许可数的计数信号量并设置为公平信号量。
  2. void acquire():从此信号量获取一个许可前线程将一直阻塞。相当于一辆车占了一个车位。
  3. void acquire(int n):从此信号量获取给定数目许可,在提供这些许可前一直将线程阻塞。比如n=2,就相当于一辆车占了两个车位。
  4. void release():释放一个许可,将其返回给信号量。就如同车开走返回一个车位。
  5. void release(int n):释放n个许可。
  6. int availablePermits():当前可用的许可数。
实例:十个工人要使用三台机器进行一些工作(十个工人为十个线程,三台机器为三个资源,每次最多只能有三个线程获得资源并执行代码)

/***
 * 模拟 10个工人 使用 三台机器
 */
public class SemaphoreDemo implements Runnable{

    private int pope;  //工人数 工人工号
    private Semaphore semaphore;  //机器数量

    public SemaphoreDemo(int pope, Semaphore semaphore) {
        this.pope = pope;
        this.semaphore = semaphore;
    }


    @Override
    public void run() {
        try {
            semaphore.acquire();  //获取资源
            System.out.println(Thread.currentThread().getName()+"正在使用机器进行工作");
            semaphore.release(); //释放资源
            System.out.println(Thread.currentThread().getName()+"使用完毕,释放资源");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo(10,semaphore);
        for(int i = 1 ; i<=10 ;i++ ){
            new Thread(semaphoreDemo,"员工"+i).start();
        }
    }
	//执行结果
	员工2正在使用机器进行工作
	员工1正在使用机器进行工作
	员工2使用完毕,释放资源
	员工1使用完毕,释放资源
	员工3正在使用机器进行工作
	员工3使用完毕,释放资源
	员工4正在使用机器进行工作
	员工4使用完毕,释放资源
	员工5正在使用机器进行工作
	员工5使用完毕,释放资源
	员工6正在使用机器进行工作
	员工6使用完毕,释放资源
	员工7正在使用机器进行工作
	员工7使用完毕,释放资源
	员工8正在使用机器进行工作
	员工8使用完毕,释放资源
	员工9正在使用机器进行工作
	员工9使用完毕,释放资源
	员工10正在使用机器进行工作
	员工10使用完毕,释放资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值