Java并发之Semaphore

Posted by Kaka Blog on July 19, 2019

简介

Semaphore是一种计数信号量,用于管理一组资源,内部是基于AQS的共享模式。它相当于给线程规定一个量从而控制允许活动的线程数。

应用场景

Semaphore与CountDownLatch相似,不同的地方在于Semaphore的值被获取到后是可以释放的,并不像CountDownLatch那样一直减到底。它也被更多地用来限制流量,类似阀门的 功能。如果限定某些资源最多有N个线程可以访问,那么超过N个主不允许再有线程来访问,同时当现有线程结束后,就会释放,然后允许新的线程进来。

使用

  • Semaphore(int permits):构造方法,创建具有给定许可数的计数信号量并设置为非公平信号量
  • Semaphore(int permits,boolean fair):构造方法,当fair等于true时,创建具有给定许可数的计数信号量并设置为公平信号量
  • acquire():用于获取权限
  • release():用于释放权限

例子

import java.util.concurrent.Semaphore;

class ZeroEvenOdd {
    private int n;
    private Semaphore lockZero = new Semaphore(1);
    private Semaphore lockOdd = new Semaphore(0);
    private Semaphore lockEven = new Semaphore(0);
    
    public ZeroEvenOdd(int n) {
        this.n = n;
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero(IntConsumer printNumber) throws InterruptedException {
        for (int i=0; i<n; i++) {
            lockZero.acquire();
            printNumber.accept(0);
            if (i % 2 == 0)
                lockOdd.release();
            else
                lockEven.release();
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        for (int i=2; i<=n; i+=2) {
            lockEven.acquire();
            printNumber.accept(i);
            lockZero.release();
        }
    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        for (int i=1; i<=n; i+=2) {
            lockOdd.acquire();
            printNumber.accept(i);
            lockZero.release();
        }
    }
}

参考