Semaphore(信号灯)
文档解释:
一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
此类的构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取许可的顺序做任何保证。特别地,闯入 是允许的,也就是说可以在已经等待的线程前为调用 acquire() 的线程分配一个许可,从逻辑上说,就是新线程将自己置于等待线程队列的头部。当公平设置为 true 时,信号量保证对于任何调用获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。注意,FIFO 排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了 acquire,但是却在该线程之后到达排序点,并且从方法返回时也类似。还要注意,非同步的 tryAcquire 方法不使用公平设置,而是使用任意可用的许可。
通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。
构造方法摘要
- Semaphore(int permits)
创建具有给定的许可数和非公平的公平设置的 Semaphore。 - Semaphore(int permits, boolean fair)
创建具有给定的许可数和给定的公平设置的 Semaphore。
方法摘要:
- void acquire()
从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 - void acquire(int permits)
从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。 - void acquireUninterruptibly()
从此信号量中获取许可,在有可用的许可前将其阻塞。 - void acquireUninterruptibly(int permits)
从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。 - int availablePermits()
返回此信号量中当前可用的许可数。 - int drainPermits()
获取并返回立即可用的所有许可。
7 .protected Collection getQueuedThreads()
返回一个 collection,包含可能等待获取的线程。 - int getQueueLength()
返回正在等待获取的线程的估计数目。 - boolean hasQueuedThreads()
查询是否有线程正在等待获取。 - boolean isFair()
如果此信号量的公平设置为 true,则返回 true。 - protected void reducePermits(int reduction)
根据指定的缩减量减小可用许可的数目。 - void release()
释放一个许可,将其返回给信号量。 - void release(int permits)
释放给定数目的许可,将其返回到信号量。 - String toString()
返回标识此信号量的字符串,以及信号量的状态。 - boolean tryAcquire()
仅在调用时此信号量存在一个可用许可,才从信号量获取许可。 - boolean tryAcquire(int permits)
仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。 - boolean tryAcquire(int permits, long timeout, TimeUnit unit)
如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。 - boolean tryAcquire(long timeout, TimeUnit unit)
如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* Semaphore: 信号灯
* 解释:一个计数信号量。从概念上讲,信号量维护了一个许可集。
* 如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。
* 每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
* 但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
* 简明解释:
* Semaphore对象中,存在一个信号值,比如存在Samephore中存在三个信号值,
* 存在6个线程,那么只有三个线程通过acquire()方法,有机会,暂时拥有Samephore一段时间
* ,一旦调用release()方法之后,那么拥有Semaphore的线程,将会失去机会
* ,被下一个拿到acquire()方法的线程,拥有Semaphore,直到调用release()方法,重复该过程
*/
public class SemaphoreUse {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(3);
for (int i = 1; i <=6 ; i++) {
new Thread(() -> {
try {
//线程拥有Semaphore对象的资格
semaphore.acquire();
//设置当前线程睡眠时间
TimeUnit.SECONDS.sleep(new Random().nextInt(2));
System.out.println(Thread.currentThread().getName() + "...拥有..Semaphore");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放当前线程拥有Semaphore对象的资格
semaphore.release();
System.out.println(Thread.currentThread().getName() + "...释放 ------- Semaphore");
}
}, "线程:" + String.valueOf(i)).start();
}
}
}