Semaphore(信号量):是一种计数器, 用来保护一个或多个共享资源的访问。 如果线程要访问一个资源就必须先获取信号量。 如果信号量内部计数器大于0, 信号量减1, 然后允许共享这个资源; 否则,如果信号量的计数器等于0, 信号量将会将线程置于休眠状态,直至计数器大于0。
注意: 信号量使用完后,必须释放。
Semaphore的常用API:
// 构造方法
public Semaphore(int permits) { //permits指定计数器大小
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) { // fair是否公平获取资源, 默认 非公平的
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
// 获取一个许可, 如果无可用许可前将一直阻塞等待
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 释放一个许可
public void release() {
sync.releaseShared(1);
}
// 从信号量尝试获取一个许可,如果无可用许可,直接返回false,不会阻塞
public boolean tryAcquire() {
return sync.nonfairTryAcquireShared(1) >= 0;
}
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
使用示例:
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(5);
for(int i=0; i<10; i++){
new Thread(()->{
try {
semaphore.acquire(); // 获取许可
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " get acquire");
semaphore.release(); // 释放许可
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "Thread"+i).start();
}
}
输出结果:
从结果中看不出来semaphore的效果, 执行的时候会发现, 它先执行前5个线程, 间隔1s后才开始执行后面的线程。这里如果把Semaphore的资源数调小, 线程的睡眠时间调大一些可能看到的效果更明显一些。