一. Semaphorer
1.1 简介
Semaphore,俗称信号量,它也是基于AbstractQueuedSynchronizer实现的。例如: 大小为n的信号量可以实现限流的功能,它可以实现只能有n个线程同时获取信号量。
1.2 Semaphore的加锁解锁(共享锁)逻辑实现
1.3 实例
一般用做限流.
public class SemaphoneTest2 {
/**
* 实现一个同时只能处理5个请求的限流器
*/
private static Semaphore semaphore = new Semaphore(5);
/**
* 定义一个线程池
*/
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 50, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(200));
/**
* 模拟执行方法
*/
public static void exec() {
try {
// acquire() 表示阻塞并获取许可
semaphore.acquire(1);
// 模拟真实方法执行
System.out.println("执行exec方法" );
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
} finally {
// release() 表示释放许可
semaphore.release(1);
}
}
public static void main(String[] args) throws InterruptedException {
{
for (; ; ) {
Thread.sleep(100);
// 模拟请求以10个/s的速度
executor.execute(() -> exec());
}
}
}
二. CountDownLatch
2.1 简介
CountDownLatch(闭锁)是一个同步协助类,允许一个或多个线程等待,直到其他线程完成操作集。
CountDownLatch使用给定的计数值(count)初始化。await方法会阻塞直到当前的计数值(count)由于countDown方法的调用达到0,count为0之后所有等待的线程都会被释放,并且随后对await方法的调用都会立即返回。这是一个一次性现象 —— count不会被重置。
2.2 实现原理
- 底层基于 AbstractQueuedSynchronizer 实现,CountDownLatch 构造函数中指定的count直接赋给AQS的state;每次countDown()则都是release(1)减1,最后减到0时unpark释放阻塞线程;这一步是由最后一个执行countdown方法的线程执行的。
- 而调用await()方法时,当前线程就会判断state属性是否为0,如果为0,则继续往下执行,如果不为0,则使当前线程进入等待状态,直到某个线程将state属性置为0,其就会唤醒在await()方法中等待的线程。
2.3 实例
参考我的另一篇文章: CountDownLatch的骚操作