我读到ThreadPoolExecutor
有线程池,这个池注定要降低创建新线程的成本(至少我以这种方式理解下面的短语):
当您向执行程序发送任务时,它会尝试使用池化线程 为了执行这项任务,避免不断产生 线程。 [Java 7 Concurrency Cookbook]
但是,我知道我们无法在Java中重启线程。
问题: ThreadPoolExecutor如何避免创建新线程?
答案 0 :(得分:10)
这很简单 - 本质上是Thread
的睡眠,等待被任务吵醒 - 他们执行该任务然后再次睡觉。
public static void main(final String[] args) throws Exception {
final BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<>();
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
blockingQueue.take().run();
} catch (InterruptedException ex) {
return;
}
}
}
});
t.start();
blockingQueue.add(new Runnable() {
@Override
public void run() {
System.out.println("Task 1");
}
});
blockingQueue.add(new Runnable() {
@Override
public void run() {
System.out.println("Task 2");
}
});
}
BlockingQueue
会阻止Thread
为空。当我添加一个项目时,当前被阻止的Thread
(s)被唤醒,并且将执行任务(LinkedBlockingDeque
是线程安全的)。当Thread
完成任务后,它会重新进入睡眠状态。
ThreadPoolExecutor
的{{3}}详细描述了逻辑。 ThreadPoolExecutor
的所有构造函数都采用BlockingQueue<Runnable>
- 这应该给出一个提示,因为逻辑是如何工作的。
注意:这与忙等待不同。 BlockingQueue
使用wait
和notify
来暂停和唤醒Thread
,这意味着池中的Thread
无法正常工作不处理任务。基于忙等待的方法将无法正常工作,因为Thread
会阻止所有CPU内核进行轮询,不允许程序继续进行(或至少严重损害程序)。