Java中的线程何时从内存中删除?

Java中的线程何时从内存中删除?,java,memory,memory-management,garbage-collection,jvm,Java,Memory,Memory Management,Garbage Collection,Jvm,从Java API文档: Java虚拟机将继续执行线程,直到执行以下操作 发生: 所有不是守护进程线程的线程都已死亡,返回 从对run方法的调用或通过引发 传播到run方法之外 我希望我的假设是正确的,即一旦线程完成其run()方法,它就有资格进行垃圾收集。在同样的背景下,我只是想知道: 如果它在返回后没有资格进行垃圾收集 从run(),是否应该将其引用设置为null 有资格进行垃圾收集并不一定意味着这一点 该对象将从内存中删除。这完全取决于 垃圾收集时的底层操作系统/JVM。 但是,如何确保(

从Java API文档:

Java虚拟机将继续执行线程,直到执行以下操作 发生:

所有不是守护进程线程的线程都已死亡,返回 从对run方法的调用或通过引发 传播到run方法之外

我希望我的假设是正确的,即一旦线程完成其
run()
方法,它就有资格进行垃圾收集。在同样的背景下,我只是想知道:

  • 如果它在返回后没有资格进行垃圾收集 从
    run()
    ,是否应该将其引用设置为
    null
  • 有资格进行垃圾收集并不一定意味着这一点 该对象将从内存中删除。这完全取决于 垃圾收集时的底层操作系统/JVM。 但是,如何确保(通过Java程序或外部工具)对象完全从中删除呢 记忆
  • 如果一个线程在完成其run()方法后被称为死线程,为什么 我仍然可以在上执行
    isAlive()
    getState()
    同一个线程对象?这两个调用都返回
    false
    RUNNABLE
    分别

  • 线程已完成执行的事实不会改变对对象的引用的有效性。当您持有该引用时,线程对象不能被垃圾回收

    这意味着,当您持有对线程的引用时,您可以调用
    isAlive
    之类的东西。当您释放所有引用时,线程可以被垃圾回收


    如果希望在不阻止对象被垃圾收集的情况下引用对象,则必须使用。当您使用这样的引用时,您必须检查引用的对象是否仍然存在。

    我认为垃圾收集器在内存中没有对象引用时收集对象。对于线程,进程正在运行,因此垃圾收集器不会收集线程对象

    每个对象树必须有一个或多个根对象。只要应用程序可以到达这些根,就可以通过

    javabook.compuware.com/content/memory/how-garbage-collection-works.aspx
    

    您似乎在Java中遇到了一个常见的陷阱:线程本身不是Java对象。它是本机资源(执行线程)。一旦完成代码的运行,它将被“从内存中删除”

    另一方面,
    Thread
    的实例只是一个普通的Java对象,它的生命周期与任何其他对象相同,除了一条额外的规则,即只要底层本机线程处于活动状态,它就保持可访问性。这意味着您可以随时调用
    Thread.currentThread()

    因此,如果保留对负责死线程的
    线程
    实例的引用,它将不会神奇地消失,其所有方法将继续按指定操作。你可以坚持多久就坚持多久


    关于你的问题2,“从记忆中移除”一个物体实际上是一个毫无意义的术语。运行时本身实际上不知道收集到的对象是那些它已经忘记的对象。

    线程类是本机内存中真实线程的代理

    我希望我的假设是正确的,即一旦线程完成其run()方法,它就有资格进行垃圾收集

    run()之后实际上有一些代码,这些代码处理未捕获的异常

    一旦线程死亡,它的本机内存和堆栈将立即释放,而不需要GC。但是,
    线程
    对象与任何其他对象一样,它会一直存在,直到GC决定它可以是自由的,例如,没有对它的强引用

    类似地,FileOutputStream是操作系统中文件的代理。即使文件已
    close()
    或已删除,您仍然可以对该对象进行引用

    如果它从run()返回后没有资格进行垃圾收集,那么应该将其引用设置为null来进行垃圾收集吗

    你几乎不需要在任何地方这样做。事实上,一开始不保留对线程的引用,或者使用ExecutorService来管理线程通常更简单

    当我有一个对象有一个
    线程
    字段时,我经常让这个对象在线程死亡时死亡,因此该字段不需要被
    删除

    我还使用用于Fork/Join的内置线程池。这是一种在后台线程中执行任务的更轻量级的方法,因为它不会创建和破坏太多线程

    ExecutorService fjp = ForkJoinPool.commonPool();
    
    符合垃圾收集条件并不一定意味着该对象将从内存中删除。垃圾收集时,它由底层操作系统/JVM自行决定。但是,如何确保(通过Java程序或外部工具)对象完全从内存中删除呢

    你不能也不应该尝试。GC将在需要时清理资源

    如果一个线程在完成其run()方法后被称为死线程,为什么我仍然能够在同一个线程对象上执行isAlive()或getState()?这两个调用分别返回false和RUNNABLE


    线程对象与任何其他对象类似。只要你对它有一个引用,就可以调用它上的方法。

    关于线程有两件事要考虑。

  • 在运行之前和运行期间,线程对象本身都是GC根,也就是说:不能收集它们和从它们强烈访问的任何对象
  • 一旦线程完成运行,它就会“恢复”为普通对象。GC规则同样适用于它们,就像适用于任何其他对象一样。例如,当你对它们有很强的引用时,它们不会被收集和保存
    class Test {
    
    protected void finalize() throws Throwable {
        System.out.println("test finalized");
    };
    
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
        Test test = new Test();
    
        try {
            System.out.println(t.getState());
            // t.join();
            t = null;
            test = null;
            // System.out.println(t.getState());
    
            Thread.sleep(500); // change this to say 2 or 3 sec i.e, until run() completes. The thread object will be finalized
            System.gc();
            System.out.println("gc call done..");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
    
    class MyThread extends Thread {
    
    protected void finalize() throws Throwable {
        System.out.println("MyThread instance finalized..");
    };
    
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            System.out.println(i);
    
        }
    }
    
    RUNNABLE
    0
    gc call done..
    test finalized
    1
    2
    3
    4
    
          RUNNABLE
        0
        gc call done..
        test finalized
        1
        2
        3
        4
    MyThread instance finalized..