在同一个线程上调用两次启动方法是否合法?

下面的代码导致java.lang.IllegalThreadStateException: Thread already started在程序中第二次调用start()方法时java.lang.IllegalThreadStateException: Thread already started

 updateUI.join(); if (!updateUI.isAlive()) updateUI.start(); 

第二次调用updateUI.start()时会发生这种情况。 我已经通过了多次,线程被调用,完成之前运行到完成updateUI.start()

调用updateUI.run()可以避免这个错误,但会导致线程在UI线程(调用线程,就像在SO上的其他post中提到的那样)中运行,这不是我想要的。

线程只能启动一次吗? 如果是这样,如果我想再次运行线程,该怎么办? 这个特定的线程是在后台做一些计算,如果我不在线程中做它比在UI线程中完成,并且用户有一个不合理的漫长的等待。

Solutions Collecting From Web of "在同一个线程上调用两次启动方法是否合法?"

Thread.start方法的Java API规范 :

多次启动线程永远不合法。 特别是一旦完成执行,线程可能不会被重新启动。

此外:

抛出:
IllegalThreadStateException – 如果线程已经启动。

所以是的,一个Thread只能启动一次。

如果是这样,如果我想再次运行线程,该怎么办?

如果一个Thread需要运行多次,那么应该创build一个Thread的新实例并调用它。

非常正确。 从文档 :

多次启动线程永远不合法。 特别是一旦完成执行,线程可能不会被重新启动。

就重复计算而言,您可以使用SwingUtilities的invokeLater方法 。 您已经在尝试直接调用run() ,这意味着您已经在考虑使用Runnable而不是原始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."); 

如果用计算来replaceprintln调用,它可能正是你所需要的。

编辑:跟随评论,我没有注意到原来的post中的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. */ 

所以,在Android世界中,您可以使用与上面相同的示例,将Swingutilities.invokeLaterreplace为适当的post给Handler

刚刚到达的答案涵盖了为什么你不应该做你在做什么。 这里有一些解决你的实际问题的选项。

这个特定的线程是在后台做一些计算,如果我不在线程中做它比在UI线程中完成,并且用户有不合理的漫长的等待。

转储自己的线程并使用AsyncTask

或者在需要时创build一个新线程。

或者设置你的线程来运行一个工作队列(例如LinkedBlockingQueue )而不是重新启动线程。

,我们不能再次启动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()方法中输出,方法完成。 线程“main”中的exceptionjava.lang.Thread.start(Unknown Source)的java.lang.IllegalThreadStateException *

检查这个

正如你所说,一个线程不能多于一次启动。

直接从马的嘴巴: Java API Spec

多次启动线程永远不合法。 特别是一旦完成执行,线程可能不会被重新启动。

如果您需要重新运行线程中发生的任何事情,则必须创build一个新线程并运行该线程。

你应该做的是创build一个Runnable,并在每次运行Runnable时用一个新的Thread包装它。 这将是非常丑陋的,但你可以用另一个线程来包装一个线程来再次运行它的代码,但只有这样做是你真的不得不这样做。

重新使用线程是Java API中的非法操作。 但是,您可以将其封装到可运行的工具中,然后重新运行该实例。

是的,我们不能启动已经运行的线程。 它将在运行时抛出IllegalThreadStateException – 如果线程已经启动。

如果您确实需要启动线程,该怎么办:选项1)如果一个线程需要运行多次,那么应该创build一个新的线程实例并调用它。

线程只能启动一次吗?

是。 你可以开始一次。

如果是这样,如果我想再次运行线程,我该怎么办?这个特定的线程正在后台进行一些计算,如果我不在线程中执行它,而不是在UI线程中完成,并且用户有不合理的漫长的等待

不要再次运行Thread 。 而是创buildRunnable并将其发布到HandlerThread的 Handler上。 您可以提交多个Runnable对象。 如果要将数据发送回UI线程,请在Runnable run()方法中,在UI线程的处理程序上发布Message ,并处理handleMessage

例如代码请参考这篇文章:

Android:在一个线程中吐司

这将是非常丑陋的,但你可以用另一个线程来包装一个线程来再次运行它的代码,但只有这样做是你真的不得不这样做。

我不得不修复由创build线程的程序员造成的资源泄漏,但不是直接启动它,而是直接调用run()方法。 所以避免它,除非你真的知道它造成的副作用。