线程池执行器:如何重用线程

10

我了解到ThreadPoolExecutor拥有一组线程池,并且该线程池旨在降低创建新线程的成本(至少我理解下面的短语是这样的):

 

当您将任务发送到执行程序时,它会尝试使用池化线程来执行此任务,以避免不断生成线程。[Java 7 Concurrency Cookbook]

但是,据我所知,在Java中没有重启线程的方法。

问题: ThreadPoolExecutor如何避免创建新的线程?

1个回答

15
很简单 - 实质上,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完成任务时,它就会回到睡眠状态。

ThreadPoolExecutorJavaDoc详细描述了逻辑。所有ThreadPoolExecutor的构造函数都需要一个BlockingQueue<Runnable> - 这应该给你一个关于逻辑如何工作的提示。

NB: 这与忙等待不同BlockingQueue使用waitnotify来挂起和唤醒Thread,这意味着当线程池中的线程不处理任务时,它们不执行任何工作。基于忙等待的方法不起作用,因为线程将通过轮询阻塞所有CPU核心,从而不允许程序继续进行(或者严重损害程序性能)。


Boris提供了不错的信息。此外,他们将每个对worker run方法的调用都包装在try-catch throwable中,以便无论调用的方法发生什么错误,线程都不会退出。或者采用其他方式来跟踪活动线程并在需要时创建新线程? - tgkprog
@tgkprog 确实是这样 - 提交的代码被包装在一个自定义的 Runnable 中,不仅处理 Exception,还通过 Callable<T> -> Future<T> API 返回执行结果。如果您想了解实现细节,最好查看源代码 - Boris the Spider
这并不是全部的故事。ThreadPoolExecutor 可能会允许线程死亡,并在它们的位置上构建新的线程。请参阅 ThreadPoolExecutor 文档中的“保持活动时间”部分。 - cambunctious
@cambunctious 这与线程的重用方式没有真正关系,而是与池化机制本身有关。 - Boris the Spider
1
@ante.sabo 不是的。线程是完全阻塞的,因此无论调用 sleep 还是阻塞 IO,它们都不会返回到池中,直到 run() 返回。你所说的,在 Java 中被称为 Fibres,并且很快将被包含在 JDK 中。反应式编程库也可以帮助解决这个问题,但是你需要非常小心地调用它的 sleep 方法(通常称为 delay),而不是 sleep 本身,因为... 线程是完全阻塞的。 - Boris the Spider
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接