我了解到ThreadPoolExecutor
拥有一组线程池,并且该线程池旨在降低创建新线程的成本(至少我理解下面的短语是这样的):
当您将任务发送到执行程序时,它会尝试使用池化线程来执行此任务,以避免不断生成线程。[Java 7 Concurrency Cookbook]
但是,据我所知,在Java中没有重启线程的方法。
问题: ThreadPoolExecutor如何避免创建新的线程?
我了解到ThreadPoolExecutor
拥有一组线程池,并且该线程池旨在降低创建新线程的成本(至少我理解下面的短语是这样的):
当您将任务发送到执行程序时,它会尝试使用池化线程来执行此任务,以避免不断生成线程。[Java 7 Concurrency Cookbook]
但是,据我所知,在Java中没有重启线程的方法。
问题: ThreadPoolExecutor如何避免创建新的线程?
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
被唤醒并且其中一个将获取任务(LinkedBlockingDeque
是线程安全的)。当Thread
完成任务时,它就会回到睡眠状态。
ThreadPoolExecutor
的JavaDoc详细描述了逻辑。所有ThreadPoolExecutor
的构造函数都需要一个BlockingQueue<Runnable>
- 这应该给你一个关于逻辑如何工作的提示。
NB: 这与忙等待不同。 BlockingQueue
使用wait
和notify
来挂起和唤醒Thread
,这意味着当线程池中的线程不处理任务时,它们不执行任何工作。基于忙等待的方法不起作用,因为线程将通过轮询阻塞所有CPU核心,从而不允许程序继续进行(或者严重损害程序性能)。
Runnable
中,不仅处理Exception
,还通过Callable<T> -> Future<T>
API 返回执行结果。如果您想了解实现细节,最好查看源代码。 - Boris the Spiderrun()
返回。你所说的,在 Java 中被称为 Fibres,并且很快将被包含在 JDK 中。反应式编程库也可以帮助解决这个问题,但是你需要非常小心地调用它的 sleep 方法(通常称为delay
),而不是 sleep 本身,因为... 线程是完全阻塞的。 - Boris the Spider