并发工具二之Semaphore

一、Semaphore简介

semaphore 也就是我们常说的信号灯,semaphore 可以控制同时访问的线程个数,通过 acquire 获取一个许可,如果没有就等待,通过 release 释放一个许可。有点类似限流的作用。

二、Semaphore使用案例

semaphore叫信号灯的原因也和他的用处有关,比如某商场就3 个停车位,每个停车位只能停一辆车,如果这个时候来了 10 辆车,必须要等前面有空的车位才能进入。

定义一个停车的线程,每次都先去获取令牌(acquire),然后再释放令牌(release)

public class Car extends Thread {

    private Semaphore semaphore;

    private int num;

    public  Car(Semaphore semaphore,int num){
        this.semaphore = semaphore;
        this.num = num;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            System.out.println("第"+num+"辆车占用停车位");
            TimeUnit.SECONDS.sleep(2);
            System.out.println("第"+num+"辆车开走了");
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

创建10个线程。模拟10个车辆,Semaphore初始化创建3个令牌模拟3个停车位

public class SemaphoreDemo {

    static Semaphore semaphore = new Semaphore(3);

    public static void main(String[] args) {
        for(int i=0;i<10;i++) {
            new Car(semaphore,i).start();
        }
    }
}

运行结果

0辆车占用停车位
第8辆车占用停车位
第4辆车占用停车位
第0辆车开走了
第3辆车占用停车位
第4辆车开走了
第8辆车开走了
第7辆车占用停车位
第1辆车占用停车位
第3辆车开走了
第5辆车占用停车位
第1辆车开走了
第9辆车占用停车位
第7辆车开走了
第2辆车占用停车位
第5辆车开走了
第6辆车占用停车位
第9辆车开走了
第2辆车开走了
第6辆车开走了

Process finished with exit code 0

三、源码分析

在分析过AQS,锁,Condition,CountDownLatch等并发工具的源码,Semaphore的源码没有必要再一行行代码解释了。
从 Semaphore 的功能来看,我们基本能猜测到它的底层实现一定是基于 AQS 的共享所,因为需要实现多个线程共享一个令牌池,创建Semaphore 实例的时候,需要一个参数 permits,这个基本上可以确定是设置给 AQS 的 state 的,然后每个线程调用 acquire 的时候,执行 state = state - 1,release 的时候执行 state = state + 1,当然,acquire 的时候,如果 state = 0,说明没有资源了,需要等待其他线程 release。

本文是综合自己的认识和参考各类资料(书本及网上资料)编写,若有侵权请联系作者,所有内容仅代表个人认知观点,如有错误,欢迎校正; 邮箱:[email protected] 博客地址:https://blog.csdn.net/qq_35576976/

你可能感兴趣的:(多线程,java,多线程)