用线程分配java内存
我想知道如果在一个方法中声明一个本地线程会发生什么?通常,函数返回时,所有局部变量都将消失,因为它们都是在堆栈上分配的。然而,本地线程似乎是另一回事。是这样吗
public int A() {
Thread t = new Thread() {
doSomething();
}
t.start();
return -1;
}
你可以在下面搜索框中键入要查询的问题!
我想知道如果在一个方法中声明一个本地线程会发生什么?通常,函数返回时,所有局部变量都将消失,因为它们都是在堆栈上分配的。然而,本地线程似乎是另一回事。是这样吗
public int A() {
Thread t = new Thread() {
doSomething();
}
t.start();
return -1;
}
# 1 楼答案
如果变量是一个原语,那么它将在堆栈上,并且在方法返回时将消失——但是线程的
Runnable
实例(或任何包含线程内容的实例)将具有该原语值的副本如果变量是引用类型,那么对象将被分配到堆上并一直存在,直到不再有对它的引用为止,此时它可以进行垃圾收集。对该对象的引用位于堆栈上,并且在方法返回时将消失,但与原语一样,线程的
Runnable
将具有该引用的副本(从而使该对象保持活动状态)# 2 楼答案
如果线程是从本地上下文启动的,则该线程将继续执行,直到其可运行的
run
方法完成执行为止# 3 楼答案
约翰的回答很好,但我想我应该补充一些细节。下面是一个代码示例,我将使用它来显示特定的变量用法
因此,我们在线程周围分配了许多变量。我们还有
Thread
对象本身以及线程正在运行的Runnable
目标startThread()
的本地线程,但关联的Thread
也由JVM管理。只有在run()
方法完成并且Thread
被JVM获取之后,它才会被GC'd。在Thread
被GC'd之后,那么Thread
使用的所有字段都可以被GC'dThread
完成后进行GC'd,并且是GC'dstartThread()
的本地值,并在堆栈上分配。当startThread()
方法完成并且堆栈被重用时,它将被覆盖李>startThread()
的本地代码,并在堆上分配。线程无法使用它,因为它不是final
。它可以在startThread()
完成后进行GC李>startThread()
的本地代码,并在堆上分配。这是final
,因此线程可以使用它,但它不是。它可以在startThread()
完成后进行GC李>startThread()
的本地代码,并在堆上分配。这是final
,线程使用它。只有在startThread()
方法完成和后Runnable
和Thread
都被GC'd,它才能被GC'dRunnable
内部的一个本地字段,在堆上作为Runnable
匿名类的一部分进行分配。它可以在Runnable
完成并且Runnable
和Thread
被GC'd之后被GC'dRunnable
内部的一个本地字段,在堆上分配。它可以在Runnable
完成并且Runnable
和Thread
被GC'd之后被GC'drun()
方法内部的一个局部字段,分配给新线程的堆栈。当run()
方法完成并且堆栈被重用时,它将被覆盖李>run()
方法内部的一个本地字段,在堆上分配。它可以在run()
方法完成后进行GC李>baz()
方法内部的一个局部字段,分配给新线程的堆栈。当baz()
方法完成并且堆栈被重用时,它将被覆盖李>baz()
方法内部的一个本地字段,在堆上分配。它可以在baz()
方法完成后进行GC李>其他几点注意事项:
startThread()
完成,就可以对其进行GC。Runnable
以及与之相关的所有变量也可以进行GC李>startThread()
中声明了一个final long varX
原语并在线程中使用,那么它必须在堆上分配,而不是在堆栈上分配。当startThread()
完成时,它仍将被使用李># 4 楼答案
如果在方法中生成局部
Thread
,则只有声明为final
的局部方法变量将一直保留到Thread
完成为止。当Thread
完成它的run()
方法时,线程和它从创建它的方法中获得的任何最终变量都将像其他任何东西一样被垃圾收集澄清
只有原始方法和派生线程的
run()
方法中使用的final
变量在方法和run()
方法完成之前不会被垃圾收集。如果线程不访问变量,那么线程的存在不会阻止在原始方法完成后对变量进行垃圾收集参考资料
http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
# 5 楼答案
线程是它自己的GC根。因此,无论何时创建线程(不管其创建上下文如何),在其run方法完成之前,它都不会准备好进行GC。即使本地方法完成并且线程仍然处于活动状态,这也是正确的
例如:
在
//do somethign else quickly
之后,任何未逃逸该方法的定义都将标记为GC。线程th将不会被标记为GC,而是正确地放置在具有自己线程堆栈的堆上