Java - java线程可以多次调用启动吗?
Posted
技术标签:
【中文标题】Java - java线程可以多次调用启动吗?【英文标题】:Java - Can java thread invoke start more than once? 【发布时间】:2011-07-26 22:41:04 【问题描述】:伙计们,
我知道这个问题在此之前已经被问过,虽然是间接的。但它并没有回答我的疑问。 问题:Is it legal to call the start method twice on the same Thread?
来自spec,
启动线程是不合法的 不止一次。特别是,一个 线程可能不会重新启动一次 已完成执行。
我同意。但是我的代码不会抛出IllegalThreadStateException
,它预计会在执行以下程序时抛出。
public class Tester extends Thread
public void run()
System.out.print("run");
public static void main(String[] args)
Tester thread = new Tester();
new Thread(thread).start();
new Thread(thread).start();
Q.1) 我在 Eclipse 中运行了上述代码。在这里,由于我试图在同一个实例上启动一个新线程,因此预计会抛出一个 IllegalThreadStateException
。但事实并非如此。
为什么?
Q.2) 如果我们确实在同一个实例上启动了一个新线程,它会有什么危害?
任何帮助将不胜感激!
【问题讨论】:
我认为这(仅)不是它会造成什么伤害的问题。我认为这更像是一个没有意义的问题。启动一个已经在运行的线程是什么意思?你能启动一辆已经在运行的汽车吗?这种想法毫无意义。 【参考方案1】:您没有在同一个实例上调用 start()。每次使用 new 时,您都在创建一个不同的实例。因此调用 start() 没有问题。
如果你这样做了:
Thread t = new Thread(thread);
t.start();
t.start();
那你可能有问题了。
【讨论】:
【参考方案2】:首先,您正在调用两个不同的线程对象,即:
new Thread(thread).start();
new Thread(thread).start();
您正在两个不同的实例上调用 start 方法。出于这个原因,您没有得到异常。
尝试使用以下方法获取异常
thread.start();
thread.start();
关于你的第二个问题。你可以在这里得到答案:Why can't we call the start method twice on a same instance of the Thread object?
幸运的是我问了这个问题:)
【讨论】:
【参考方案3】:java线程可以多次调用start吗?
您可以随意使用 start()。但是,如果您在 same 线程上多次调用它,则会收到 IllegalThreadStateException。
Q.1) 我在 Eclipse 中运行了上述代码。在这里,由于我试图在同一个实例上启动一个新线程,因此预计会抛出 IllegalThreadStateException。但事实并非如此。
那是因为您创建了 三个 不同的线程。一个是Tester,两个包裹Tester。
Q.2) 如果我们确实在同一个实例上启动了一个新线程,它会有什么危害?
除了制造混乱,没有。你不应该这样做。相反,Tester 应该实现 Runnable。
【讨论】:
【参考方案4】:Q.1) 我在 Eclipse 中运行了上述代码。在这里,由于我试图在同一个实例上启动一个新线程,因此预计会抛出 IllegalThreadStateException。但事实并非如此。
您没有在同一个实例上调用 start()。
new Thread(thread).start();
上面的说法同
new Thread((Runnable)thread).start();
【讨论】:
【参考方案5】:在这里,我们看到了为什么 Executors 如此有意义。
典型的惯用 Java 会说您根本不应该运行自己的线程。创建一个执行器服务,并让它管理线程。您只需创建 Runnable 实例并将其传递给 executor 服务;您可以随意调用 Runnable 的 run() 方法,无论何时何地都有意义,此时您不必担心线程管理。
延长线程也是一次性的;在 Java 中扩展超类是昂贵的(因为你得到一个超类,就是这样)。但是,您可以根据需要扩展任意数量的接口,因此 Runnable 还为您提供了更强大的对象层次结构。
【讨论】:
这个答案与我的问题有什么关系? 好吧,IMO,从表面上看,你的问题的答案很明显:不,在同一个 Thread 实例上调用 start() 两次是不合法的。第一个问题使用了一个无效的假设(您没有在同一个 Thread 实例上调用 start() 两次,而是创建了两个单独的 Thread 实例)。第二个问题没有实际意义,因为Thread的定义意味着你不能启动两次;你会得到一个非法的状态。所以我所做的就是试着去想你想要完成的可能的任务。使用 runnables 意味着您可以似乎运行两次。【参考方案6】:由于大多数答案都涵盖了 Q1,因此我想专注于 Q2,即“如果我们确实在同一个实例上启动了一个新线程,它会有什么危害?”
要考虑的第一点是你想在什么时候第二次调用线程启动方法,是在第一个线程执行时(案例:1)还是在第一个线程执行完成后(案例2)
case1:要识别启动和执行的线程,我们拥有的唯一方法是用于创建的线程对象,因此如果有机会第二次调用 start() 方法,则假设其他线程被创建并执行,但是如果我们想更改/操作在特定实例上执行的多个线程中的特定线程,我们将如何单独识别它们,所以完全不可能,因此唯一地识别正在运行的线程和处理它 java 不允许多次调用 start() 方法。
案例2:如果已经运行的线程已经完成,为什么java不允许我们多次调用start()方法? 在java中,一旦对象的范围结束,它就需要被垃圾收集,所以在线程对象的情况下也会发生这种情况,但是如果有多次调用start方法的设施,java env不应该允许GC发生线程对象认为可能有第二次使用该线程对象,并且该线程对象将永远处于堆中(或某个地方)而不会获得 GC。
所以考虑到以上两个原因,他们可能对在线程对象上调用 start() 方法进行了限制。
【讨论】:
以上是关于Java - java线程可以多次调用启动吗?的主要内容,如果未能解决你的问题,请参考以下文章