在同一个线程上调用两次启动方法是否合法?
下面的代码导致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线程中完成,并且用户有不合理的漫长的等待。
从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.invokeLater
replace为适当的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()方法。 所以避免它,除非你真的知道它造成的副作用。