java - 在同一个线程上调用start方法两次是合法的吗?
当我在程序中第二次调用updateUI.start()方法时,以下代码导致updateUI.run()。
updateUI.join();
if (!updateUI.isAlive())
updateUI.start();
这是第二次调用updateUI.run()时发生的。 我已经多次执行它并且调用线程并且在完成updateUI.start()之前完成运行完成。
调用updateUI.run()可以避免错误,但会导致线程在UI线程(调用线程,如SO上的其他帖子中提到)中运行,这不是我想要的。
线程只能启动一次吗? 如果我想再次运行该线程怎么办? 这个特定的线程在后台进行一些计算,如果我不在线程中执行它而不是在UI线程中完成,并且用户有一个不合理的漫长等待。
10个解决方案
107 votes
从Thread方法的Java API规范:
启动一个线程永远不合法 不止一次。 特别是,a 一旦线程可能无法重新启动 已完成执行。
此外:
抛出:
Thread - 如果线程已经启动。
所以是的,Thread只能启动一次。
如果是这样,如果我愿意,我该怎么做 再次运行线程?
如果需要多次运行Thread,则应该创建Thread的新实例并在其上调用start。
coobird answered 2019-09-11T05:20:20Z
13 votes
非常正确。 从文档:
启动一个线程永远不合法 不止一次。 特别是,a 一旦线程可能无法重新启动 已完成执行。
就重复计算可以做什么而言,似乎可以使用SwingUtilities invokeLater方法。 您已经在尝试直接调用Swingutilities.invokeLater,这意味着您已经在考虑使用Handler而不是原始Thread。尝试在Runnable任务上使用invokeLater方法,看看它是否更符合您的心理模式。
以下是文档中的示例:
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.");
如果用计算替换Swingutilities.invokeLater调用,它可能正是您所需要的。
编辑:跟进评论,我没有注意到原帖中的Android标记。 相当于Android工作中的invokeLater是Swingutilities.invokeLater.来自它的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.
*/
因此,在Android世界中,您可以使用与上面相同的示例,将Swingutilities.invokeLater替换为适当的帖子Handler。
Bob Cross answered 2019-09-11T05:21:23Z
3 votes
刚到的答案涵盖了为什么你不应该做你正在做的事情。 以下是解决实际问题的一些选项。
这个特定的线程正在做一些 在后台计算,如果我 不要在线程中执行它而不是它 在UI线程中完成并且用户具有 一段不合理的漫长等待。
转储您自己的线程并使用LinkedBlockingQueue。
或者在需要时创建一个新线程。
或者将线程设置为在工作队列(例如,LinkedBlockingQueue)之外操作,而不是重新启动线程。
CommonsWare answered 2019-09-11T05:22:16Z
3 votes
不,我们无法再次启动Thread,这样做会抛出runtimeException java.lang.IllegalThreadStateException。>
原因是一旦run()方法被Thread执行,它就进入死状态。
我们举一个例子 - 考虑再次启动线程并在其上调用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
}
}
/ *在run()方法中输出OUTPUT,方法已完成。 线程中的异常 “main”java.lang.IllegalThreadStateException 在java.lang.Thread.start(未知来源) */
检查一下
Sameer Kazi answered 2019-09-11T05:23:11Z
2 votes
你应该做的是创建一个Runnable,并在每次要运行Runnable时用新线程包装它。这样做真的很难看,但是你可以用另一个线程包装一个线程来再次运行它的代码,但这只是你必须这样做。
Peter Lawrey answered 2019-09-11T05:23:38Z
1 votes
正如你所说,一个线程不能多次启动。
直接来自马口:Java API Spec
启动一个线程永远不合法 不止一次。 特别是,a 一旦线程可能无法重新启动 已完成执行。
如果你需要重新运行你的线程中发生的任何事情,你将不得不创建一个新线程并运行它。
alanlcode answered 2019-09-11T05:24:20Z
0 votes
重用线程是Java API中的非法操作。但是,您可以将其包装到可运行的实现中,然后再次重新运行该实例。
Aaron He answered 2019-09-11T05:24:48Z
0 votes
是的,我们无法启动已经运行的线程。如果线程已经启动,它将在运行时抛出IllegalThreadStateException。
如果你真的需要启动线程怎么办:选项1)如果一个线程需要多次运行,那么应该创建一个新的Thread实例并在其上调用start。
riteeka answered 2019-09-11T05:25:22Z
0 votes
线程只能启动一次吗?
是。 你可以开始一次。
如果我想再次运行该线程,我该怎么做?这个特定的线程在后台进行一些计算,如果我不在线程中执行它而不是在UI线程中完成并且用户有一个不合理的 漫长的等待。
不要再次运行Thread。 而是创建Runnable并将其发布在HandlerThread的Handler上。 您可以提交多个Runnable个对象。 如果想要将数据发送回UI线程,请使用Runnable run()方法,在Handler的UI线程上发布Message并处理handleMessage
有关示例代码,请参阅此帖子:
Android:在线程中敬酒
Ravindra babu answered 2019-09-11T05:26:24Z
-1 votes
这样做真的很难看,但是你可以用另一个线程包装一个线程来再次运行它的代码,但这只是你必须这样做。
我不得不修复由创建Thread但没有start()的程序员引起的资源泄漏,他直接调用了run()方法。 所以要避免它,除非你真的知道它会导致什么副作用。
Torben answered 2019-09-11T05:26:59Z