为什么不能重新启动Java Thread对象?

Cur*_*urd 14 java multithreading

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

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

示例代码:

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
Run Code Online (Sandbox Code Playgroud)

lui*_*nal 18

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

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

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

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

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

太毛茸茸,太复杂了.所有这些都是微不足道的收获.最好将Threads保留为不可复制的资源.


And*_*yle 15

我想提出一个问题倒过来-为什么一个Thread对象可重新启动?

可以说更容易推理(并且可能实现)一个只执行一次给定任务的线程,然后永久完成.要重新启动线程,需要更复杂地查看程序在给定时间处于什么状态.

因此,除非你能想出一个特定的原因,为什么重新启动给定的Thread是一个更好的选择而不仅仅是创建一个具有相同的新选项Runnable,我认为设计决策是更好的.

(这与关于final变量与变量的论证大致类似- 我发现最终的"变量"更容易推理,而更愿意创建多个新的常量变量,而不是重用现有变量.)

  • @Curd - 你有没有对你的应用程序进行分析,发现对象分配和线程GC的成本构成了不可忽视的运行时成本?除非你做某事*疯狂*,否则几乎肯定不会.在这种情况下,只需将`Runnable`发送到一个线程池(例如`ThreadPoolExecutor`). (3认同)