Semaphore:控制并发访问的个数。
Semaphore就像是去餐厅吃饭的问题,例如:去餐厅吃饭正好是下课时间人比较多,而且有20个都想要去买饼吃,而且一起到,但是只有3个餐厅窗口是卖饼的。这个时候我们就需要去排队。而Semaphore可以解决排队这个问题,只有当前面的人卖完之后,我们才可以释放一个窗口让其它同学来买饼。由以下代码可以看出semaphore.acquire()来进行排队,当卖完饼走人时,这个时候可以释放一个窗口semaphore.release()让其它同来买饼semaphore.acquire(),而买饼窗口的的数量取决于new Semaphore(X)的大小。
package com.jiaoshou.concurency.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author yangkaifei
* @date 2018/12/11 13:38
*/
@Slf4j
public class SemaphoreExample {
//线程数(买饼人数)
private static int threadCount=20;
public static void main(String[] args)throws InterruptedException {
//线程池
ExecutorService exec=Executors.newCachedThreadPool();
//允许并发数(窗口数)
final Semaphore semaphore=new Semaphore(3);
for (int i =0; i < threadCount; i++) {
final int threadNum=i;
exec.execute(
()->{
try {
semaphore.acquire();//拿到一个许可(买饼占用一个窗口)
test(threadNum);//要做并发控制的代码(买饼操作)
semaphore.release();//释放一个许可(卖完并离开,释放一个窗口)
}catch (Exception e) {
e.printStackTrace();
log.info("出现异常");
}
});
}
exec.shutdown();//关闭线程池
}
private static void test(int number)throws Exception {
log.info("{}",number);
Thread.sleep(1000);
}
}
在现实生活中还可以会遇见这样的情况,
1、例如一个恶霸,他也喜欢吃饼,但是这个人非常霸道非要一个人占用3个窗口,这个时候用代码可以这样去实现semaphore.acquire(3),3代表的是这个恶霸一次排队要霸占3个窗口。
2、可能买饼的同学还会遇到这样的情况,刚下课就去买饼,同样还是20个人一起到,这20个人都没有耐心。如果他们尝试这占不到窗口就不买饼,遇到这种情况我么只需要将try里面的代码改为。如果这样的情况下,很明显只有3位同学(开放的窗口数量)能买到饼
if(semaphore.tryAcquire()){//尝试获取一个许可(尝试排队)
test(threadNum);//要做并发控制的代码(买饼)
semaphore.release();//释放X个许可(离开)
}
3、还是例2的情况,但是现在同学们变的有耐心了,同学们都可以接受等5秒,如果5秒内还没有占到买饼窗口就离开不买饼吃了。这个时候只需将tryAcquire加个参数就可以
if(semaphore.tryAcquire(5000,TimeUnit.MILLISECONDS)){//尝试获取一个许可,5秒内