一Semaphore
通过许可证管理多个线程的执行,有许可证的线程可以执行,没有许可证的线程会等待。
二Semaphore方法说明
- Semaphore(permits):初始化许可证数量的构造函数
- Semaphore(permits,fair):初始化许可证数量和是否公平模式的构造函数
- isFair():是否公平模式FIFO
- availablePermits():获取当前可用的许可证数量
- acquire():
- 当前线程尝试去获取1个许可证。此过程是阻塞的,它会一直等待许可证,直到发生以下事:
- 当前线程获取了1个可用的许可证,则会停止等待,继续执行。
- 当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
- acquire(permits):
- 当前线程尝试去获取permits个许可证。此过程是阻塞的,它会一直等待许可证,直到发生以下事
- 当前线程获取了n个可用的许可证,则会停止等待,继续执行。
- 当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
- acquierUninterruptibly():
- 当前线程尝试去阻塞的获取1个许可证(不可中断的)。此过程是阻塞的,它会一直等待许可证,直到发生以下事
- 当前线程获取了1个可用的许可证,则会停止等待,继续执行。
- acquireUninterruptibly(permits):
- 当前线程尝试去阻塞的获取permits个许可证。此过程是阻塞的,它会一直等待许可证,直到发生以下事
- 当前线程获取了n个可用的许可证,则会停止等待,继续执行。
- tryAcquire():当前线程尝试去获取1个许可证。
- 此过程是非阻塞的,它只是在方法调用时进行一次尝试。
- 如果当前线程获取了1个可用的许可证,则会停止等待,继续执行,并返回true。
- 如果当前线程没有获得这个许可证,也会停止等待,继续执行,并返回false。
- tryAcquire(permits):当前线程尝试去获取permits个许可证。
- 此过程是非阻塞的,它只是在方法调用时进行一次尝试。
- 如果当前线程获取了permits个可用的许可证,则会停止等待,继续执行,并返回true。
- 如果当前线程没有获得permits个许可证,也会停止等待,继续执行,并返回false。
- tryAcquire(timeout,TimeUnit):当前线程在限定时间内,阻塞的尝试去获取1个许可证
- 此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
- 当前线程获取了可用的许可证,则会停止等待,继续执行,并返回true。
- 当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
- 当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
- tryAcquire(permits,timeout,TimeUnit):当前线程在限定时间内,阻塞的尝试去获取permits个许可证。
- 此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
- 当前线程获取了可用的permits个许可证,则会停止等待,继续执行,并返回true。
- 当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
- 当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
- release():当前线程释放1个可用的许可证。
- release(permits):当前线程释放permits个可用的许可证。
- drainPermits():当前线程获得剩余的所有可用许可证。
- hasQueuedThreads():判断当前Semaphore对象上是否存在正在等待许可证的线程。
- getQueueLength():获取当前Semaphore对象上是正在等待许可证的线程数量。
三案例
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Semaphore sp = new Semaphore(3);
for (int i = 0; i < 4; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
sp.acquire();//获取许可证
System.out.println("执行:线程" + Thread.currentThread().getName());
System.out.println("当前许可证数量:" + sp.availablePermits());
System.out.println("每个线程走到这里都等待5秒");
Thread.sleep(5000);
System.out.println("正在等待许可证的线程数量:" + sp.getQueueLength());
sp.release();//释放许可证
System.out.println("当前许可证数量:" + sp.availablePermits());
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
};
service.execute(runnable);
}
}
}
四结果分析
执行:线程pool-1-thread-2
当前许可证数量:2
每个线程走到这里都等待5秒
执行:线程pool-1-thread-1
当前许可证数量:1
每个线程走到这里都等待5秒
执行:线程pool-1-thread-4
当前许可证数量:0
每个线程走到这里都等待5秒------------解释
代码都到这里,说明有3个线程(2,1,4)拿到许可证并执行了,有一个线程还没有拿到许可证,因为总的许可证只有3个。
------------解释
正在等待许可证的线程数量:1
当前许可证数量:1------------解释
当前许可证数量1,说明已经有一个线程释放了许可证,那么等待许可证的那个线程可以执行了
------------解释
执行:线程pool-1-thread-3
当前许可证数量:0
每个线程走到这里都等待5秒
正在等待许可证的线程数量:0
当前许可证数量:1
正在等待许可证的线程数量:0
当前许可证数量:2
正在等待许可证的线程数量:0
当前许可证数量:3