应用场景:多个线程使用数量有限的资源。

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

public class Semaphore implements java.io.Serializable {
    // 最多支持N个资源访问
    public Semaphore(int permits);

    // 获取可用的资源,
    // 如果可用, 信号量内部的资源个数减掉1,
    // 如果没有可用资源线程会阻塞在该方法中,不能结束该方法,不能返回,直到有可用的资源为止
    public void acquire() throws InterruptedException;

    // 当前可用的资源个数, permits - availablePermits() = 正在使用的资源个数
    public int availablePermits();

    // 释放资源,释放后信号量内部的资源个数会增加1
    // 如果有被阻塞的线程,释放后会唤醒一个线程去获取资源
    // acquire() 和 release()要成对使用,一般release()放在finally代码块中
    public void release();
}

多线程(十二): 信号量Semaphore_信号量

public class SemaphoreTest {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 10; i++) {
            new Thread(new MyRunnable(semaphore), "第" + i + "个人").start();
        }
    }
}

class MyRunnable implements Runnable {
    private Semaphore semaphore;
    public MyRunnable(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        int availablePermits = semaphore.availablePermits();
        if (availablePermits > 0) {
            System.out.println(name + "无人,可用");
        } else {
            System.out.println(name + "有人,请排队。。。\t?");
        }

        try {
            // 如果没有拿到资源将一直等待,直到有人释放,拿到资源
            semaphore.acquire();
            System.out.println(name + "轮到我了");
            // 模拟使用时间
            Thread.sleep(1000);
            System.out.println(name + "使用完毕\t?");
        } catch (InterruptedException e) {
        } finally {
            // 使用完释放资源
            semaphore.release();
        }
    }
}

多线程(十二): 信号量Semaphore_释放资源_02