Semaphore
Semaphore叫做信号量,和前⾯两个不同的是,它的计数器是递增的。
public class SemaphoreTest {
private static int num =3;
private static int initNum =0;
private static Semaphore semaphore =new Semaphore(initNum);
private static ExecutorService executorService =
Executors.newFixedThreadPool(num);
public static void main(String[] args) throws Exception {
executorService.submit(() ->{
System.out.println("A在上厕所");
try {
Thread.sleep(4000);
semaphore.release();
System.out.println("A上完了");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
});
executorService.submit(() ->{
System.out.println("B在上厕所");
try {
Thread.sleep(2000);
semaphore.release();
System.out.println("B上完了");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
});
executorService.submit(() ->{
System.out.println("C在上厕所");
try {
Thread.sleep(3000);
semaphore.release();
System.out.println("C上完了");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
});
System.out.println("等待所有⼈从厕所回来开会...");
semaphore.acquire(num);
System.out.println("所有⼈都好了,开始开会...");
executorService.shutdown();
}
}
输出结果为:
稍微和前两个有点区别,构造函数传⼊的初始值为0,当⼦线程调⽤release()⽅法时,计数器递增,主线程acquire()传参为3则说明主线程⼀直阻塞,直到计数器为3才会返回。
Semaphore还还还是基于AQS实现的,同时获取信号量有公平和⾮公平两种策略
1. 主线程调⽤acquire()⽅法时,⽤当前信号量值-需要获取的值,如果⼩于0,则进⼊同步阻塞队列,⼤于0则通过CAS设置当前信号量为剩余值,同时返回剩余值
2. ⼦线程调⽤release()给当前信号量值计数器+1(增加的值数量由传参决定),同时不停的尝试因为调⽤acquire()进⼊阻塞的线程