介绍
信号量支持多线程同时并发,但是同时并发线程数是确定的,起到了限流的作用。比如: 临界资源的数量是5个,那么则可以同时支持5个线程进入临界资源,待进入临界资源的线程退出后,其他线程才能进入来,也就是说当前占用临界资源的线程小于5个,其他线程才能进来。以停车场的车位为例: 停车场有5个车位,如果都停满了车,那么其他车就无法进来;反之,其他车可以进入停车场,直接到车位停满。
使用
初始化信号量
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
permits表示信号量个数(即临界资源个数),默认采用非公平同步策略。
尝试获取信号量
public boolean tryAcquire() {
return sync.nonfairTryAcquireShared(1) >= 0;
}
判断是否有可用的信号量,非阻塞调用,如果有,直接返回true,反之返回false
尝试在指定时间内获取信号量
public boolean tryAcquire(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
在指定时间内尝试获取信号量,阻塞调用(在指定时间内),如果有,直接返回true,反之返回false
timeout 超时时间
unit 超时时间单位
获取信号量
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
直接获取信号量,阻塞调用,如果有可用信号量,直接返回,信号量个数减一;如果可用信号量为0,则阻塞
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
同时获取几个信号量,阻塞调用,如果有足够可用信号量,直接返回,信号量个数减permits;如果可用信号量小于permits,则阻塞
释放新号量
public void release() {
sync.releaseShared(1);
}
释放一个信号量,信号量个数加1,如果有线程阻塞在acquire()函数,那么将被唤醒,并获取到信号量,并往下执行。
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
释放permits个信号量(表示释放临界资源个数),信号量个数加permits
清空信号量
public int drainPermits() {
return sync.drainPermits();
}
将信号量个数清零,此时无可用的信号量
获取等待线程个数
public final int getQueueLength() {
return sync.getQueueLength();
}
该方法可以判断有多少线程阻塞在获取信号量函数上(即有多少线程调用了acquire())
测试例子
代码:
package sample;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(24);
// int count = semaphore.availablePermits();
// System.out.println("可用信号量 count1: " + count);
// //增加20个信号量
// semaphore.release(20);
int count = s