为什么 Java 线程对象无法重新启动?

2022-09-03 09:39:00

我知道不可能重新启动使用的Java Thread对象,但我没有找到为什么不允许这样做的解释;即使保证线程已完成(请参阅下面的示例代码)。

我不明白为什么(或者至少是一个)方法不能以某种方式将Thread对象的内部状态 ( 无论它们是什么 - 重置为它们在新创建Thread对象时具有的相同值。start()restart()

示例代码:

class ThreadExample {

  public static void main(String[] args){

    Thread myThread = new Thread(){
      public void run() {
        for(int i=0; i<3; i++) {
          try{ sleep(100); }catch(InterruptedException ie){}
          System.out.print(i+", ");
        }
        System.out.println("done.");
      }
    };

    myThread.start();

    try{ Thread.sleep(500); }catch(InterruptedException ie){}
    System.out.println("Now myThread.run() should be done.");

    myThread.start(); // <-- causes java.lang.IllegalThreadStateException

  } // main

} // class

答案 1

我知道不可能重新启动使用的Java Thread对象,但我没有找到为什么不允许这样做的解释;即使保证线程已完成(请参阅下面的示例代码)。

我的认知是,线程可能直接绑定(为了提高效率或其他约束)到实际的本机资源,这些资源可能在某些操作系统中可以重新启动,但在其他操作系统中则不能。如果 Java 语言的设计者允许重新启动 Threads,他们可能会限制 JVM 可以运行的操作系统的数量。

想想看,我想不出一个允许线程或进程在完成或终止后重新启动的操作系统。当一个过程完成时,它就会死亡。你想要另一个,你重新启动它。你永远不会复活它。

除了底层操作系统施加的效率和限制问题之外,还有分析和推理的问题。当事物不可变或具有离散的有限生命周期时,您可以对并发性进行推理。就像状态机一样,它们必须具有终端状态。它是开始,等待,完成吗?如果你允许Threads复活,这样的事情就不容易推理出来。

您还必须考虑复活线程的含义。重新创建它的堆栈,它的状态,是安全的复活吗?你能复活一个异常结束的线程吗?等。

太毛茸茸,太复杂。所有这些都是为了微不足道的收益。最好将线程保留为不可复活的资源。


答案 2

我会反过来提出这个问题 - 为什么Thread对象应该是可重新启动的?

可以说,推理(并且可能实现)一个线程要容易得多,该线程只是执行其给定任务一次,然后永久完成。要重新启动线程,需要一个更复杂的视图来了解程序在给定时间处于什么状态。

因此,除非你能想出一个具体的原因,为什么重启一个给定是一个更好的选择,而不是仅仅创建一个具有相同条件的新选择,否则我认为设计决策是更好的。ThreadRunnable

(这与关于可变变量与变量的争论大致相似 - 我发现最终的“变量”更容易推理,并且宁愿创建多个新的常量变量,而不是重用现有的变量。final