semaphore基于AQS共享锁。
    (1)主要方法:

    • new Semaphore(3):创建令牌个数为3;
    • .acquire():获取令牌,令牌数量减一;
    • .release():释放令牌,令牌数量加一;
    • .availablePermits():剩余令牌数量;

    (2)阻塞队列:

    • 入队:当令牌数量为0时,尝试获取令牌失败,进入等待队列;
    • 出队:当有线程释放令牌时,唤醒等待队列中的所有线程,竞争令牌。令牌数量为0,再进入等待队列;

    (3)使用示例

    1. public void testSemaphore() {
    2. for (int i = 0; i < 10; i++) {
    3. new Thread(()->{
    4. try {
    5. System.out.println("========" + Thread.currentThread().getName() + "来到停车场");
    6. if(semaphore.availablePermits() == 0){
    7. System.out.println("停车位已满");
    8. }
    9. semaphore.acquire();
    10. System.out.println(Thread.currentThread().getName() + "进入");
    11. Thread.sleep(new Random().nextInt(1000));
    12. System.out.println(Thread.currentThread().getName() + "离开");
    13. semaphore.release();
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. },i + "号车").start();
    18. }
    19. }

    (4)图解:

    • 当有5个线程尝试获取3个令牌:Semaphore - 图1
    • 线程1、2、4获取到令牌,0、3没有获取到进入AQS等待队列:
      Semaphore - 图2
    • 此时,线程4释放令牌,线程0从队列出队,获得令牌:
      Semaphore - 图3