为什么在java中,线程一旦启动,就再也不能启动了

为什么在java中,线程一旦启动,就再也不能启动了,java,multithreading,Java,Multithreading,我知道“线程一旦启动,就再也不能启动了” 但我想知道为什么 如果允许以后在另一个时间重新启动,会有什么问题 为什么,你只能在线程处于新状态时启动它?为什么它至少在死后也不能出现? public class ThreadDemo { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); t

我知道“线程一旦启动,就再也不能启动了”
但我想知道为什么
如果允许以后在另一个时间重新启动,会有什么问题
为什么,你只能在线程处于新状态时启动它?为什么它至少在死后也不能出现?

public class ThreadDemo {

    public static void main(String[] args) {

        Thread thread = new Thread(new MyRunnable());
        thread.start();
        thread.start(); // java.lang.IllegalThreadStateException

    }

}

class MyRunnable implements Runnable{

    @Override
    public void run() {

        System.out.println("run().Thread.currentThread().getName() : " + Thread.currentThread().getName());

    }
}
注:我已经看过这些了。但我的问题更具体、更具描述性


在这里,请注意,我想了解这一点主要是为了了解线程的内部功能以及GC等相关方面如何与线程状态一起工作。

,因为
线程
实现不允许这样做。您总是可以使用
Runnable
之类的工具创建另一个
Thread
实例

new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
编辑

(部分地)说

如果所有动作都以与程序顺序一致的总顺序(执行顺序)发生,则一组动作顺序一致,而且变量v的每个读取r都看到由写入w写入v的值,从而:

w comes before r in the execution order, and

there is no other write w' such that w comes before w' and w' 
comes before r in the execution order.
顺序一致性是程序执行过程中可见性和顺序的有力保证。在顺序一致的执行中,所有单个操作(如读写)的总顺序与程序的顺序一致,每个单独的操作都是原子的,每个线程都可以立即看到


如果
线程
实例可以再次启动,那么顺序一致性的实现很可能是不可能的。

如果查看线程的生命周期,它将被创建,然后移动到线程池中等待执行


一旦它的工作完成,它就会被调度器破坏,因此系统不再知道它(空引用)-因此它不能再次启动,正如Elliot所建议的,创建一个新线程来执行
MyRunnable
函数是完全正确的,但是命名线程的执行对于它的作用域来说是唯一的

我可以给你一些要点

  • 垃圾收集:活动线程被视为垃圾收集的根。 表示如果某个对象可以从活动线程访问,则无法对其进行垃圾收集。
    现在,如果一个线程处于非活动(死)状态,任何gc算法都将确定,如果一个只有该线程才能访问的特定对象现在有资格进行垃圾收集,那么它将进行垃圾收集 那个物体。但现在,如果您再次使线程处于活动状态,这将是一个问题,因为它的堆栈视图将被破坏,因为许多对象可能已被垃圾收集。 你的整个计划都会失控

    为了解决这个问题,您需要再维护一个状态,我们称之为GC\u COLLECTABLE。 这意味着线程处于活动状态意味着其状态!=可收藏的。现在问题来了 程序员何时设置此状态。这与无法停止线程或确定何时必须对某些对象进行垃圾收集的问题是相同的。这本身就是一个需要解决的非常复杂的问题。解决此问题的最简单方法是在线程死后不让其处于活动状态,或者无法重新启动它

  • thread.join():如Eliott所建议。假设有三个线程T1 T2和一个可重启线程RST。现在假设T1和T2都调用RST.join()。 T1和T2脱离联接时出现问题。若线程可以再次启动,那个么join方法是无限的。如果允许join在死状态后返回,则存在争用和未确定的行为,导致T1完成join(),但T2仍然存在,因为RST已经重新启动

  • API更改:您建议如何实现此功能

    Thread.start();//这种方法够了吗。可能不会

    如果我打电话会怎么样 循环中的Thread.start() ->如果以前的线程失败,它会创建新线程吗 没有死线程或将重新启动死线程(听起来像是执行器。newCachedThreadPools

    ->或者,如果当前线程没有死机,则抛出异常,或者重新启动线程 这不是一个很好的方法,它将使您的程序更加不确定。因为同一个线程可以为同一个任务花费不同的时间,因此您将无法预测程序输出。 至少,您需要对start方法中的已检查异常进行签名更改,或者定义一个新的方法restart,但它会遇到与上面相同的问题

  • 从我的角度来看,仅第一点就足以避免重新启动线程。
    此外,您还可以通过使用线程池来实现类似的功能,在线程池中,可以将线程重新用于不同/类似的任务

    如果您查看线程的生命周期,它被创建,然后移动到一个线程池中等待执行——一旦它的工作完成,它就会被调度程序破坏,因此系统不再知道它(空引用)-因此它不能再次启动-正如Elliot在下面建议的那样,完全可以装箱一个新线程来执行
    MyRunnable
    函数,但是命名线程的执行对于其作用域是唯一的。@Alex这应该作为一个答案发布。这比埃利奥特的解释要好得多!是的。调用start()后,新线程将转到池中。我们手头有再次调用start()的引用。但我想问的是,为什么至少在国家死后,它不能再次运行。如果允许的话,会有什么问题?明白。但是为什么呢?我想问的是,为什么至少在国家死后,它不能再次运行。如果它允许的话,会有什么问题呢?也许我的示例很糟糕,任何线程都可能与另一个线程共享状态(事实上,很多线程都是这样做的,因为Java不是一个纯粹的线程)