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线程可以多次调用启动吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java 多线程 资源冲突

Java线程中run和start方法的区别

Java并发----线程常见方法总结

Java 多线程启动

Java 多线程启动

Files.copy 是 Java 中的线程安全函数吗?