Semaphore 阻塞之信号灯

现在大家用并发场景用的比较多,或者说异步场景下怎么等待异步结果,再parallelStream场景下虽然有分开合并的功能,但是再普通的线程池下是没有此功能的,所以有时候要用到Semaphore 信号灯,废话不多说,先解释一下Semaphore :

Semaphore是一个计数信号量,它的本质是一个”共享锁”。

信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

再普通的场景下异步锁用的是synchronized同步锁, synchronized的语义是互斥锁,就是在同一时刻,只有一个线程能获得执行代码的锁。但是现实生活中,有好多的场景,锁不止一把。而我们有的时候是不希望一个人独享,而是多个人共享,比如说,又到了十一假期,买票是重点,必须圈起来。在购票大厅里,有5个售票窗口,也就是说同一时刻可以服务5个人。要实现这种业务需求,用synchronized显然不合适(参考https://blog.csdn.net/buyaoxx/article/details/77935730)

具体方法:

// 创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits)
// 创建具有给定的许可数和给定的公平设置的 Semaphore。
Semaphore(int permits, boolean fair)
// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void acquire()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
void acquire(int permits)
// 从此信号量中获取许可,在有可用的许可前将其阻塞。
void acquireUninterruptibly()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
void acquireUninterruptibly(int permits)
// 返回此信号量中当前可用的许可数。
int availablePermits()
// 获取并返回立即可用的所有许可。
int drainPermits()
// 返回一个 collection,包含可能等待获取的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待获取的线程的估计数目。
int getQueueLength()
// 查询是否有线程正在等待获取。
boolean hasQueuedThreads()
// 如果此信号量的公平设置为 true,则返回 true。
boolean isFair()
// 根据指定的缩减量减小可用许可的数目。
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)

用法:先用Semaphore()申请锁,然后acquire()用掉这个信号量然后再需要等待的地方再重新申请锁,sp.tryAcquire(30, TimeUnit.SECONDS);这时候如果没有申请到就会被阻塞,这个带有超时机制,这样就可以再此处等待。如果再异步线程中release过了,后面的tryacquire就可以通过,这样就实现了异步后的重新同步。


猜你喜欢

转载自blog.csdn.net/zouheliang/article/details/80010738