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

本文深入解析了CountDownLatch、CyclicBarrier和Semaphore三种并发控制工具的原理与应用。CountDownLatch用于等待一组线程完成任务;CyclicBarrier使多个线程在到达某个点时同步;Semaphore则控制同时访问共享资源的线程数量。
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使用完毕,释放资源
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值