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