ThreadPoolExecutor:它如何重用线程

时间:2014-03-01 09:21:23

标签: java multithreading concurrency

我读到ThreadPoolExecutor有线程池,这个池注定要降低创建新线程的成本(至少我以这种方式理解下面的短语):

  

当您向执行程序发送任务时,它会尝试使用池化线程   为了执行这项任务,避免不断产生   线程。 [Java 7 Concurrency Cookbook]

但是,我知道我们无法在Java中重启线程。

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

1 个答案:

答案 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使用waitnotify来暂停和唤醒Thread,这意味着池中的Thread无法正常工作不处理任务。基于忙等待的方法将无法正常工作,因为Thread会阻止所有CPU内核进行轮询,不允许程序继续进行(或至少严重损害程序)。