synchronized和ReentrantLock,在任一时刻都只允许一个线程访问临界资源,而Semaphore可以允许多个线程同时访问临界资源。
构造信号量时需要指定许可数,即允许同时访问的线程数量。
private static final Semaphore SEMAPHORE = new Semaphore(5);
说明:构造函数的第二个参数表示是否公平,即根据先进先出的顺序获取许可。
信号量的主要方法有:
public void acquire();	// 获取许可,如果无法获取,则线程等待直到被中断或成功获取到许可
public void acquireUninterruptibly(); // 获取许可,如果无法获取,则线程等待直到成功获取到许可,不响应中断
public boolean tryAcquire();	// 尝试获取许可,成功则返回true,否则返回false
public boolean tryAcquire(long timeout, TimeUnit unit); // 尝试获取许可,如果无法获取,等待指定时间
public void release();	// 释放一个许可
注意:
tryAcquire()与ReentrantLock的tryLock()方法类似,无论锁是否公平,线程总是会立即获取可用的许可,而不论是否有其它线程在等待。
try {
  SEMAPHORE.acquire();
  TimeUnit.SECONDS.sleep(3);
  System.out.println(Thread.currentThread().getId() + ": I'm done.");
  // System.out.println("-------------------------------------------");
} catch (InterruptedException exception) {
  exception.printStackTrace();
} finally {
  SEMAPHORE.release();
}