0 背景
不久前,标哥(此乃一位技术非常厉害的我的同事)曾让我看过一段很有意思的代码。这段代码的目的是通过信号量控制向线程池中提交任务,避免在线程池中大量积压任务影响程序执行效率。
我简化了一下,大概的逻辑如下:
// 实际工作的线程数,假设是4
static final int THREAD_CNT = 4;
public static void doWork() throws InterruptedException {
// 使用了核心线程数和最大线程数都为4,且使用SynchronousQueue作为等待队列的线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_CNT, THREAD_CNT, 0l, TimeUnit.MINUTES, new SynchronousQueue<>());
// 使用令牌数等于线程数,都是4的信号量控制任务提交速率
Semaphore semaphore = new Semaphore(THREAD_CNT);
while (true) {
semaphore.acquire();
executor.execute(() -> {
// 这里面是业务逻辑,假设是打印时间戳
System.out.println(System.currentTimeMillis());
semaphore.release();
});
}
}
在提交任务的主线程中调用Semaphore.acquire()
,在具体的执行线程执行结束时调用Semaphore.release()
方法。
这段代码跑起来后,立刻就报错了:
这是为啥呢?
1 SynchronousQueue
SynchronousQueue
有一对方法:
-
offer()
:向队列中插入元素,如果有线程等待获取则插入成功,否则插入失败;