java线程重用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2324030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java thread reuse
提问by Bob
I have always read that creating threads is expensive.
I also know that you cannot rerun a thread.
我一直读到创建线程很昂贵。
我也知道您不能重新运行线程。
I see in the doc of Executors
class:
我在Executors
课堂文档中看到:
Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
创建一个线程池,根据需要创建新线程,但在可用时将重用先前构造的线程。
Mind the word 'reuse'.
注意“重用”这个词。
How do thread pools 'reuse' threads?
线程池如何“重用”线程?
采纳答案by SyntaxT3rr0r
I think I understood what is confuzzabling you so here's my longer answer: the terminology is a tiny bit misleading (obviously, or you wouldn't ask that question specifically putting the emphasis on 'reuse'):
我想我明白什么让你感到困惑,所以这是我更长的答案:术语有点误导(显然,或者你不会问这个问题,特别强调“重用”):
How do thread pools 'reuse' threads?
线程池如何“重用”线程?
What is happening is that a single thread can be used to process several tasks (typically passed as Runnable
, but this depend on your 'executor' framework: the default executors accepts Runnable
, but you could write your own "executor" / thread-pool accepting something more complex than a Runnable
[like, say, a CancellableRunnable
]).
发生的事情是单个线程可用于处理多个任务(通常作为 传递Runnable
,但这取决于您的“执行程序”框架:默认执行程序接受Runnable
,但您可以编写自己的“执行程序”/线程池接受某些内容比Runnable
[like, say, a CancellableRunnable
])更复杂。
Now in the default ExecutorService
implementation if a thread is somehow terminated while still in use, it is automatically replaced with a new thread, but this is not the 'reuse' they're talking about. There is no "reuse" in this case.
现在在默认ExecutorService
实现中,如果一个线程在仍在使用时以某种方式终止,它会自动替换为一个新线程,但这不是他们正在谈论的“重用”。在这种情况下没有“重用”。
So it is true that you cannot call start()
on a Java Thread twice butyou can pass as many Runnable
as you want to an executor and each Runnable
's run()
method shall be called once.
因此,它是真实的,你不能说start()
在一个Java线程的两倍,但你可以通过尽可能多的Runnable
,只要你想执行人和各Runnable
的run()
方法将被调用一次。
You can pass 30 Runnable
to 5 Java Thread
and each worker thread may be calling, for example, run()
6 times (practically there's not guarantee that you'll be executing exactly 6 Runnable
per Thread
but that is a detail).
您可以传递 30Runnable
到 5 个 Java,Thread
并且每个工作线程可能正在调用,例如,run()
6 次(实际上不能保证您将执行 6Runnable
个,Thread
但这是一个细节)。
In this example start()
would have been called 6 times. Each one these 6 start()
will call exactly oncethe run()
method of each Thread
:
在这个例子start()
中将被调用 6 次。每个人这6start()
将调用仅一次的run()
每个方法Thread
:
From Thread.start()
Javadoc:
来自Thread.start()
Javadoc:
* Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread.
* Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread.
BUTthen inside each Thread's run()
method Runnable
shall be dequeued and the run()
method of each Runnable
is going to be called. So each thread can process several Runnable
. That's what they refer to by "thread reuse".
但是然后在每个线程的run()
方法中Runnable
应该出列并且run()
每个方法的方法Runnable
将被调用。所以每个线程可以处理多个Runnable
. 这就是他们所说的“线程重用”。
One way to do your own thread pool is to use a blocking queue on to which you enqueue runnables and have each of your thread, once it's done processing the run()
method of a Runnable
, dequeue the next Runnable
(or block) and run its run()
method, then rinse and repeat.
做自己的线程池的一种方法是使用阻塞队列,在该队列上将可运行对象排入队列并拥有每个线程,一旦处理完run()
a的方法Runnable
,将下一个Runnable
(或块)出列并运行其run()
方法,然后冲洗并重复。
I guess part of the confusion (and it is a bit confusing) comes from the fact that a Thread
takes a Runnable
and upon calling start()
the Runnable 's run()
method is called while the default thread pools alsotake Runnable
.
我想部分混乱(有点令人困惑)来自这样一个事实,即 aThread
接受 aRunnable
并且在调用start()
Runnable 的run()
方法时被调用,而默认线程池也接受Runnable
。
回答by AndiDog
The thread pool consists of a number of fixed worker threads that can take tasks from an internal task queue. So if one task ends, the thread does notend but waits for the next task. If you abort a thread, it is automatically replaced.
线程池由许多固定的工作线程组成,可以从内部任务队列中获取任务。所以,如果一个任务结束时,线程并没有结束,但下个任务等待。如果您中止一个线程,它将被自动替换。
Look at the documentationfor more details.
查看文档以获取更多详细信息。
回答by Mike Daniels
The run
method of threads in a thread pool does not consist only of running a single task. The run
method of a thread in a thread pool contains a loop. It pulls a task off of a queue, executes the task (which returns back to the loopwhen it is complete), and then gets the next task. The run
method doesn't complete until the thread is no longer needed.
该run
线程的线程池的方法并不只包括运行单个任务。run
线程池中线程的方法包含一个循环。它从队列中拉出一个任务,执行该任务(完成后返回循环),然后获取下一个任务。在run
不再需要线程之前,该方法不会完成。
Edited to add:
编辑添加:
Here is the run
method of the Worker
inner class in ThreadPoolExecutor.
这里是ThreadPoolExecutor内部类的run
方法。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: }
回答by sjain
A thread pool creates its own threads and supplies its own clever little Runnables for those threads. Those Runnables never end but synchronize on a queue (they wait()) until a Callable is present in that queue; they are notified when that happens and their Runnable runs the Callable from the queue and the entire scenario repeats itself again.
线程池创建自己的线程并为这些线程提供自己聪明的小 Runnable。那些 Runnable 永远不会结束,而是在队列上同步(它们 wait()),直到该队列中存在 Callable;当发生这种情况时,他们会收到通知,并且他们的 Runnable 从队列中运行 Callable,整个场景再次重复。