java线程重用

时间:2010-02-24 06:06:11

标签: java multithreading

我一直认为创建线程很贵 我也知道你不能重新运行一个帖子。

我在Executors课程的文档中看到了:

  

创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程。

注意'重复'这个词。

线程池如何'重用'线程?

4 个答案:

答案 0 :(得分:48)

我想我明白了什么让你困惑所以这里是我的答案:这个术语有点误导(显然,或者你不会特别强调'重用'这个问题):

线程池如何“重用”线程?

发生的事情是单个线程可用于处理多个任务(通常以Runnable传递,但这取决于您的'执行者'框架:默认执行者接受Runnable,但是您可以写自己的“执行者”/线程池接受比Runnable更复杂的东西[比如说,CancellableRunnable]。

现在在默认的ExecutorService实现中,如果一个线程在仍然在使用时以某种方式被终止,它将自动被一个新线程替换,但这不是他们所讨论的'重用'。在这种情况下没有“重用”。

所以你不能两次在Java线程上调用start() 但是你可以将任意数量的Runnable传递给执行者,每个{{1} } Runnable方法应该被调用一次。

您可以将30 run()传递给5个Java Runnable,并且每个工作线程可能正在调用,例如Thread 6次(实际上并不保证您将完全执行每run() 6 Runnable,但这是一个细节。

在此示例中,Thread将被调用6次。这6个start()中的每一个都会调用一次每个start()的{​​{1}}方法:

来自run() Javadoc:

Thread

但是然后在每个线程的Thread.start()方法 * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. 内部将被出列,并且将调用每个run()的{​​{1}}方法。因此每个线程可以处理多个Runnable。这就是他们所谓的“线程重用”。

执行自己的线程池的一种方法是使用一个阻塞队列,在这个阻塞队列中对runnables进行排队并让每个线程在处理run()的{​​{1}}方法后出列,然后出列下一个Runnable(或阻止)并运行其Runnable方法,然后冲洗并重复。

我想部分混乱(而且有点混乱)来自于run()需要Runnable并且在调用Runnable Runnable的{{1}时调用方法时,默认线程池run()

答案 1 :(得分:14)

线程池中的run线程方法不仅包含运行单个任务。线程池中线程的run方法包含一个循环。它从队列中拉出任务,执行任务(当完成时将返回到循环),然后获取下一个任务。在不再需要该线程之前,run方法不会完成。

编辑添加:

以下是ThreadPoolExecutorrun内部类的Worker方法。

696:         /**
697:          * Main run loop
698:          */
699:         public void run() {
700:             try {
701:                 Runnable task = firstTask;
702:                 firstTask = null;
703:                 while (task != null || (task = getTask()) != null) {
704:                     runTask(task);
705:                     task = null; // unnecessary but can help GC
706:                 }
707:             } finally {
708:                 workerDone(this);
709:             }
710:         }

答案 2 :(得分:5)

线程池由许多固定工作线程组成,这些线程可以从内部任务队列中获取任务。因此,如果一个任务结束,则线程结束,但等待下一个任务。如果中止线程,则会自动替换它。

查看documentation了解更多详情。

答案 3 :(得分:1)

线程池创建自己的线程并为这些线程提供自己聪明的小Runnables。那些Runnables永远不会结束但是在队列上同步(等待())直到该队列中存在Callable;当发生这种情况时会通知他们,并且他们的Runnable从队列中运行Callable,整个场景再次重复。