Reputation: 8473
I am wondering what happen if you declare a local thread within a method? Normally all the local variables will be gone as soon as the function returns since they are all allocated on Stack. However, it seems that a local thread would be a different story. Is that right?
public int A() {
Thread t = new Thread() {
doSomething();
}
t.start();
return -1;
}
Upvotes: 3
Views: 6031
Reputation: 116918
John's answer is good but I thought I'd add some more details. Here's a code example that I'll use to show specific variable usage.
public void startThread() {
long var1 = 10;
byte[] var2 = new byte[1024];
final byte[] var3 = new byte[1024];
final byte[] var4 = new byte[1024];
Thread thread = new Thread(new Runnable() {
private long var5 = 10;
private byte[] var6 = new byte[1024];
public void run() {
int var7 = 100;
byte[] var8 = new byte[1024];
System.out.println("Size of var4 is " + var4.length);
baz();
...
}
private void baz() {
long var9 = 2;
byte[] var10 = new byte[1024];
...
}
});
thread.start();
}
So we have a number of variables here allocated around a thread. We also have the Thread
object itself as well as the Runnable
target the thread is running.
startThread()
, the associated Thread
is also managed by the JVM. It is only GC'd after the run()
method finishes and the Thread
is reaped by the JVM. After the Thread
is GC'd then all of the fields used by the Thread
can be GC'd.Thread
finishes and is GC'd.startThread()
and allocated on the stack. It will be overwritten when the startThread()
method finishes and the stack is reused.startThread()
and allocated on the heap. It cannot be used by the thread since it is not final
. It can be GC'd after startThread()
finishes.startThread()
and allocated on the heap. This is final
so it could be used by the thread but it is not. It can be GC'd after startThread()
finishes.startThread()
and allocated on the heap. This is final
and it is used by the thread. It can only be GC'd after both the startThread()
method finishes and the Runnable
and the Thread
are GC'd.Runnable
and allocated on the heap as part of the Runnable
anonymous class. It can be GC'd after the Runnable
finishes and the Runnable
and the Thread
are GC'd.Runnable
and allocated on the heap. It can be GC'd after the Runnable
finishes and the Runnable
and the Thread
are GC'd.run()
method and allocated on the stack of the new thread. It will be overwritten when the run()
method finishes and the stack is reused.run()
method and allocated on the heap. It can be GC'd after the run()
method finishes.baz()
method and allocated on the stack of the new thread. It will be overwritten when the baz()
method finishes and the stack is reused.baz()
method and allocated on the heap. It can be GC'd after the baz()
method finishes.Couple other notes:
startThread()
finishes. The Runnable
and all of the variables associated with it can be GC'd then as well.final long varX
primitive declared in startThread()
and used in the thread, then it must be allocated on the heap and not the stack. When startThread()
finishes it will still be in use.Upvotes: 7
Reputation: 4569
If you spawn a local Thread
within a method, only the local method variables declared as final
will stick around until the Thread
has completed. When the Thread
completes its run()
method, the thread and any final variables it had available to it from the method that created it will get garbage collected like everything else.
Clarification
Only final
variables used within the original method AND the spawned Thread's run()
method will refrain from being garbage collected until both the method and the run()
method completes. If the thread doesn't access the variable, then the presence of the thread will not prevent the variable from being garbage collected after the original method completes.
References
http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
Upvotes: -1
Reputation: 40266
A Thread is its own GC root. So any time you create a thread despite its creation context it will not be ready to GC until its run method completes. This is true even if the local method completes and the thread is still alive.
Example:
public void doSomeAsync(){
Thread th = new Thread(new Runnable(){
public void run(){
Thread.sleep(500);
}
});
th.start();
//do something else quickly
}
After //do somethign else quickly
anything defined that did not escape the method is then marked for GC. Thread th will not be marked for GC and is correctly placed on the heap with it's own thread-stack.
Upvotes: 14
Reputation: 43401
If the variable is of a primitive, then it'll be on the stack and will be gone when the method returns -- but your thread's Runnable
instance (or whatever contains the meat of the thread) will have a copy of that primitive value.
If the variable is of a reference type, then the object is allocated on the heap and lives until there are no more references to it, at which point it's eligible for garbage collection. The reference to that object is on the stack and will be gone when the method returns, but as with primitives, the thread's Runnable
will have a copy of that same reference (and will thus keep that object alive).
Upvotes: 0
Reputation: 28707
If a Thread is started from a local context, the thread will continue to execute until it's Runnable's run
method has completed execution.
Upvotes: 0