Semaphore限流
在许可可用前会阻塞每一个 acquire(),然后再获取该许可。
每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
Semaphore 只对可用许可的号码进行计数,并采取相应的行动。拿到信号量的线程可以进入代码,否则就等待。
JDK online doc
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
应用
- 数据库访问连接数
- 打印机
场景描述
用户去两个窗口买票,一个窗口同时只能接收一个用户
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* 描述:
* 信号量
*
* @author zhaojianyu
* @create 2019-01-18 9:13 AM
*/
public class MySemaphore {
class SemaphoreRunable implements Runnable{
/**
* 信号量 和 用户数
*/
private Semaphore semaphore;
private int userNum;
public SemaphoreRunable(Semaphore semaphore, int userNum) {
this.semaphore = semaphore;
this.userNum = userNum;
}
@Override
public void run() {
//获取信号量许可
try {
semaphore.acquire();
System.out.println("用户["+userNum+"]进入窗口,准备买票");
Thread.sleep((long)(Math.random()*1000));
System.out.println("用户["+userNum+"]买票完成");
Thread.sleep((long)(Math.random()*1000));
System.out.println("用户["+userNum+"]离开售票窗口");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void execute(){
//定义窗口个数
final Semaphore semaphore = new Semaphore(2);
//使用线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
//模拟20用户
for (int i = 0; i < 20; i++) {
threadPool.execute(new SemaphoreRunable(semaphore,i+1));
}
threadPool.shutdown();
}
public static void main(String[] args){
MySemaphore mySemaphore = new MySemaphore();
mySemaphore.execute();
}
}