信号量Semaphore
信号量Semaphore
信号量Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个“共享锁”。
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。
信号量Semaphore是一个非负整数(>=1)。当一个线程想要访问某个共享资源时,它必须要先获取Semaphore,当Semaphore >0时,获取该资源并使Semaphore – 1。如果Semaphore值 = 0,则表示全部的共享资源已经被其他线程全部占用,线程必须要等待其他线程释放资源。当线程释放资源时,Semaphore则+1。
实现
其内部也是通过队列同步器实现。
abstract static class Sync extends AbstractQueuedSynchronizer
构造函数
也分为公平的信号量和不公平的信号量,其中默认的为不公平的。
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
主要的公共方法
//获得一个访问许可,如果没有可用资源或者被中断,则阻塞
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//对中断不敏感
public void acquireUninterruptibly() {
sync.acquireShared(1);
}
//再被调用的时候有资源则获取,否则返回false
public boolean tryAcquire() {
return sync.nonfairTryAcquireShared(1) >= 0;
}
//在规定时间内且未被中断
public boolean tryAcquire(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//释放一个资源
public void release() {
sync.releaseShared(1);
}
//返回可用的资源数
public int availablePermits() {
return sync.getPermits();
}
//获得并返回所有可以获得的资源数
public int drainPermits() {
return sync.drainPermits();
}
。。。
还有三个方法就不写了
使用示例
火车站有五个停靠点,有七辆,每辆火车停2秒
package my.syn;
import java.util.concurrent.Semaphore;
/**
* @ClassName: MyStation
* @author: Yang.X.P
* @date: 2018-09-18 09:22
**/
public class MyStation {
static Semaphore semaphore = new Semaphore(5);
public static void main(String[] args) {
Train train = new Train();
for (int i = 0; i < 7; i++) {
Thread trainThread = new Thread(train);
trainThread.start();
}
}
}
class Train implements Runnable {
@Override
public void run() {
if(MyStation.semaphore.availablePermits() ==0) {
System.out.println(Thread.currentThread().getName()+"火车暂无可停靠点,正在等待" );
}
try {
MyStation.semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"火车进站停2秒" );
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+"火车开出停靠点" );
} catch (InterruptedException e) {
e.printStackTrace();
}
MyStation.semaphore.release();
}
}
参考资料: