Java 在同一个线程上两次调用 start 方法是否合法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1215548/
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
Is it legal to call the start method twice on the same Thread?
提问by Will
The following code leads to java.lang.IllegalThreadStateException: Thread already started
when I called start()
method second timein program.
以下代码导致java.lang.IllegalThreadStateException: Thread already started
我在程序中第二次调用start()
方法。
updateUI.join();
if (!updateUI.isAlive())
updateUI.start();
This happens the secondtime updateUI.start()
is called. I've stepped through it multiple times and the thread is called and completly runs to completion before hitting updateUI.start()
.
这发生在第二次updateUI.start()
被调用。我已经多次通过它,线程被调用并在点击之前完全运行到完成updateUI.start()
。
Calling updateUI.run()
avoids the error but causes the thread to run in the UI thread (the calling thread, as mentioned in other posts on SO), which is not what I want.
调用updateUI.run()
避免了错误,但会导致线程在 UI 线程(调用线程,如 SO 上的其他帖子中所述)中运行,这不是我想要的。
Can a Thread be startedonly once? If so than what do I do if I want to run the thread again? This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
一个线程只能启动一次吗?如果是这样,如果我想再次运行该线程该怎么办?这个特定的线程在后台做一些计算,如果我不在线程中做而不是在 UI 线程中做,并且用户有一个不合理的长时间等待。
采纳答案by coobird
From the Java API Specificationfor the Thread.start
method:
来自该方法的Java API 规范Thread.start
:
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
多次启动一个线程是不合法的。特别是,线程一旦完成执行就可能不会重新启动。
Furthermore:
此外:
Throws:
IllegalThreadStateException
- if the thread was already started.
抛出:
IllegalThreadStateException
- 如果线程已经启动。
So yes, a Thread
can only be started once.
所以是的, aThread
只能启动一次。
If so than what do I do if I want to run the thread again?
如果是这样,如果我想再次运行该线程该怎么办?
If a Thread
needs to be run more than once, then one should make an new instance of the Thread
and call start
on it.
如果 aThread
需要多次运行,那么应该创建一个新实例Thread
并调用start
它。
回答by alanlcode
It is as you said, a thread cannot be started more than once.
正如你所说,一个线程不能启动多次。
Straight from the horse's mouth: Java API Spec
马口不提:Java API Spec
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
多次启动一个线程是不合法的。特别是,线程一旦完成执行就可能不会重新启动。
If you need to re-run whatever is going on in your thread, you will have to create a new thread and run that.
如果您需要重新运行线程中发生的任何事情,则必须创建一个新线程并运行它。
回答by CommonsWare
The just-arrived answer covers why you shouldn't do what you're doing. Here are some options for solving your actual problem.
刚刚得到的答案涵盖了为什么你不应该做你正在做的事情。以下是解决您的实际问题的一些选项。
This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
这个特定的线程在后台做一些计算,如果我不在线程中做而不是在 UI 线程中做,并且用户有一个不合理的长时间等待。
Dump your own thread and use AsyncTask
.
转储您自己的线程并使用AsyncTask
.
Or create a fresh thread when you need it.
或者在需要时创建一个新线程。
Or set up your thread to operate off of a work queue (e.g., LinkedBlockingQueue
) rather than restarting the thread.
或者将您的线程设置为从工作队列(例如,LinkedBlockingQueue
)运行,而不是重新启动线程。
回答by Bob Cross
Exactly right. From the documentation:
非常正确。 从文档:
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
多次启动一个线程是不合法的。特别是,线程一旦完成执行就可能不会重新启动。
In terms of what you can do for repeated computation, it seems as if you could use SwingUtilities invokeLater method. You are already experimenting with calling run()
directly, meaning you're already thinking about using a Runnable
rather than a raw Thread
. Try using the invokeLater
method on just the Runnable
task and see if that fits your mental pattern a little better.
就重复计算可以做什么而言,似乎可以使用SwingUtilities invokeLater method。您已经在尝试run()
直接调用,这意味着您已经在考虑使用 aRunnable
而不是 raw Thread
。尝试invokeLater
仅在Runnable
任务上使用该方法,看看它是否更适合您的心理模式。
Here is the example from the documentation:
这是文档中的示例:
Runnable doHelloWorld = new Runnable() {
public void run() {
// Put your UI update computations in here.
// BTW - remember to restrict Swing calls to the AWT Event thread.
System.out.println("Hello World on " + Thread.currentThread());
}
};
SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");
If you replace that println
call with your computation, it might just be exactly what you need.
如果你println
用你的计算替换那个调用,它可能正是你所需要的。
EDIT: following up on the comment, I hadn't noticed the Android tag in the original post. The equivalent to invokeLater in the Android work is Handler.post(Runnable)
. From its javadoc:
编辑:跟进评论,我没有注意到原始帖子中的 Android 标签。相当于 Android 作品中的 invokeLater 是Handler.post(Runnable)
. 从它的javadoc:
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
So, in the Android world, you can use the same example as above, replacing the Swingutilities.invokeLater
with the appropriate post to a Handler
.
因此,在 Android 世界中,您可以使用与上面相同的示例,将 替换Swingutilities.invokeLater
为Handler
.
回答by Peter Lawrey
What you should do is create a Runnable and wrap it with a new Thread each time you want to run the Runnable. It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
你应该做的是创建一个 Runnable 并在每次你想要运行 Runnable 时用一个新的线程包装它。这样做真的很难看,但是您可以将一个线程与另一个线程包装在一起以再次为其运行代码,但只有在您真正必须这样做时才这样做。
回答by Torben
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
这样做真的很难看,但是您可以将一个线程与另一个线程包装在一起以再次为其运行代码,但只有在您真正必须这样做时才这样做。
I have had to fix a resource leak that was caused by a programmer who created a Thread but instead of start()ing it, he called the run()-method directly. So avoid it, unless you really really know what side effects it causes.
我不得不修复由创建线程的程序员引起的资源泄漏,但他没有启动(),而是直接调用了 run() 方法。所以避免它,除非你真的知道它会导致什么副作用。
回答by Aaron He
To re-use a thread is illegal action in Java API. However, you could wrap it into a runnable implement and re-run that instance again.
在 Java API 中重用线程是非法行为。但是,您可以将它包装到一个可运行的工具中并再次重新运行该实例。
回答by Sameer Kazi
No, we cannot start Thread again, doing so will throw runtimeException java.lang.IllegalThreadStateException. >
不,我们不能再次启动 Thread,这样做会抛出 runtimeException java.lang.IllegalThreadStateException。>
The reason is once run() method is executed by Thread, it goes into dead state.
原因是一旦 run() 方法被 Thread 执行,它就会进入死状态。
Let's take an example- Thinking of starting thread again and calling start() method on it (which internally is going to call run() method) for us is some what like asking dead man to wake up and run. As, after completing his life person goes to dead state.
让我们举个例子 - 考虑再次启动线程并在其上调用 start() 方法(内部将调用 run() 方法)对我们来说有点像要求死人醒来并运行。因为,在完成他的生命后,人会进入死亡状态。
public class MyClass implements Runnable{
@Override
public void run() {
System.out.println("in run() method, method completed.");
}
public static void main(String[] args) {
MyClass obj=new MyClass();
Thread thread1=new Thread(obj,"Thread-1");
thread1.start();
thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
}
}
/*OUTPUT in run() method, method completed. Exception in thread "main" java.lang.IllegalThreadStateException at java.lang.Thread.start(Unknown Source) */
/* OUTPUT in run() 方法,方法完成。线程“main”中的异常 java.lang.IllegalThreadStateException at java.lang.Thread.start(Unknown Source) */
回答by riteeka
Yes we can't start already running thread. It will throw IllegalThreadStateException at runtime - if the thread was already started.
是的,我们不能启动已经运行的线程。它会在运行时抛出 IllegalThreadStateException - 如果线程已经启动。
What if you really need to Start thread: Option 1 ) If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
如果你真的需要启动线程怎么办:选项1)如果一个线程需要运行多次,那么应该创建一个线程的新实例并调用它的启动。
回答by Ravindra babu
Can a Thread be started only once?
一个线程只能启动一次吗?
Yes. You can start it exactly once.
是的。您可以只启动一次。
If so than what do I do if I want to run the thread again?This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
如果是这样,如果我想再次运行线程,我该怎么办?这个特定的线程正在后台进行一些计算,如果我不在线程中进行计算,那么它会在 UI 线程中进行,并且用户有一个不合理的漫长的等待。
Don't run the Thread
again. Instead create Runnableand post it on Handlerof HandlerThread. You can submit multiple Runnable
objects. If want to send data back to UI Thread, with-in your Runnable
run()
method, post a Message
on Handler
of UI Thread and process handleMessage
不要再运行了Thread
。而是创建Runnable并将其发布在HandlerThread 的Handler上。您可以提交多个对象。如果想将数据发送回UI线程,:在你的 方法,张贴在UI线程和进程Runnable
Runnable
run()
Message
Handler
handleMessage
Refer to this post for example code:
有关示例代码,请参阅此帖子: