1.概述
Semaphore 信号量,相当于一个计数器,通常用来限制线程的数量。 每个线程操作前会先获取一个许可证,逻辑处理完成之后就归还这个许可证。
通俗的解释:相当于一个停车场,有10个停车位,进来一个车,占一个停车位,停满了,再有车进来,就要在门口等待, 等出去了一个车,就可以再进来一个车。
2.使用
public class SemaphoreTest {
// 定义10个线程
private static int THREAD_COUNT = 10;
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
//指定最多只能有五个线程同时执行
Semaphore semaphore = new Semaphore(5);
for (int i = 0; i < 10; i++) {
final int no = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
//获得许可,如果当前没有可用的许可证,则该线程将被阻塞,直到有可用的许可证为止
semaphore.acquire();
System.out.println("线程名称: " + Thread.currentThread().getName() + "," + no + "获得许可,时间" + LocalDateTime.now());
//模拟车辆通行耗时
Thread.sleep(2000);
//释放许可
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();
}
}
3.运行结果:
只能有5个线程同时运行。另外5个被堵塞了。
4.原理分析
4.1 构造方法
4.2 获取许可证
semaphore.acquire()
4.3 可中断的共享锁:doAcquireSharedInterruptibly
4.4 公平跟非公平锁的区别
AQS 的 hasQueuedPredecessors()
4.5 hasQueuedPredecessors
通过 #hasQueuedPredecessors() 方法,判断该线程是否位于 CLH 队列的列头,从而实现公平锁。