Thread keeping a reference forever - java

I have a class:
class RenderView implements Runnable {
Thread renderThread;
public void run() {
while(!Thread.currentThread().isInterrupted()) {
//does some work
}
}
//At some point in executed code, inside RenderView class (i'm sure it's executed)
renderThread = new Thread (this);
//When activity is closed (also, i'm sure this part is executed)
renderThread.interrupt();
And the renderThread really stops (at least, the run() method quits).
But for some reason, there is still some reference to renderView in my code, after i exit the activity. This is causing me a huge memory leak.
And a hprof dump tells me:
java.lang.Thread (this one is in GC Root)
has a reference to
target (mypackage.RenderView)
I have no idea why this Thread class is keeping a reference to my Thread, even though i've already finished the Thread! Any ideas?
EDIT: The renderView is referenced in, say, Activity B. So, when i exit the activity, no reference to renderThread should still be reachable. But still i tried setting renderThread = null : doesn't work. As i was able to find out via MAT Analyzer, the only thing that keeps renderView from being Garbage Collected is this weir reference from java.lang.Thread.

Why don't you just use an AsyncTask or runOnUIThread()?
I've never seen a need for what your doing. Perhaps there is one but otherwise just use AsyncTask or runOnUIThread. Don't reinvent the wheel.

Release your thread instance with
renderThread = null;
A thread instance is as any other instance, an object. Even if it finished running, you keep the reference to it, until you release it.

did you try to nullify renderThread?

Actually, renderThread.interrupt may not stop the thread, it is just setting a flag and singnals JVM that it can be interrupted.That is why may be your thread is still running.The best practice is gracefully exit from run method by just setting a flag in the while loop.
while(isRunning){
}
// at some point, say
isRunning = false;
The best practices on Android UI design can be had from the following link.
Android UI design pattern:

Related

In java, does a Thread keep going even if nothing can access it?

So, you've got a java class ExampleThread that extends Thread. To make this example simple, let's say that its run() method simply sleep()s for 10 seconds and then prints "Hello World" to the screen. However, it gets created like so:
public void startThread() {
//Create local variable
ExampleThread example = new ExampleThread();
example.start();
}
If we call this method and then the main thread goes on to do other things, will the Hello World get printed or not? Most Java objects cease to exist the moment nothing can refer to them (and nothing can refer to 'example', seeing as it was a local variable). Are running threads different?
Sorry if this has already been asked, I couldn't find anything about it.
Most Java objects cease to exist the moment nothing can refer to them...
For all practical purposes, that is true, but in reality, there may be an interval of time before the garbage collector reclaims the object.
...and nothing can refer to 'example', seeing as it was a local variable
There's your mistake.
First of all, example is not the Thread object. example is a variable that refers to the Thread object. example exists in the activation record for your startThread() call, and it ceases to exist as soon as startThread() returns, but the Thread object exists on the heap. And,...
...There is another reference to it that is not visible in your program.
The Thread object is not a thread. It is merely a proxy for the actual operating system thread that was created when you called example.start(). Before example.start() returns, it has created a new operating system thread including the stack for that thread. Somewhere on the stack for the new thread, below the call to the run() method, there is a call to a private method with a local variable that refers to the Thread object.
That hidden local variable is what keeps the Thread from being garbage collected until after run() has returned. Every thread in a Java program has a hidden reference to its own Thread object.
Even if you don't hold a reference to that thread, it still is referenced internally by the ThreadGroup. Otherwise you'd be right that the thread would be expected to be destroyed by the Garbage Collector. So no special handling here, but a non-so-obvious reason.
The daemon attribute - as mentioned in the comments - has nothing to do here. If only daemon threads are left, the Java Virtual Machine is shutting down but both types of threads are handled in the same way.

Control Android Java Thread

In my Android App there is an activity that contains a runnable inner class.
From this activity a new Thread running the inner class is created/started.
This thread executes this loop:
while (run) {
...
}
The state of the boolean "run" should be changed from both threads.
Thats why I put it into the activity class like this:
private static volatile boolean run;
I would like to know if this is a correct way of controlling a thread.
Do both threads use the same variable in the memory?
As neither checking nor setting a boolean is an atomic operation for the cpu, is it possible, that one thread checks "run" while the other thread is changing its state?
A thread will stop itself if the task you placed in the inner Runnable class was completed. So, keeping the Runnable alive will make the thread alive too, i.e. using while loop. And volatile boolean controls the change of run variable easily.
Do both threads use the same variable in the memory?
Yes. You haven't shown us much code, but since the variable is static, you've shown us enough. A static variable only exists in one place. Any code that can see it anywhere in your program is seeing the same variable.
I would like to know if this is a correct way of controlling a thread.
It is a fine way of signalling a thread.
The only reason why you might want to do differently is if the thread is not able to check the run variable often enough. Especially, if the thread waits for anything.
In that case, you might want to look into thread.interrupt() Interrupting any thread while it is waiting for something (in most cases) will cause the method that was waiting to throw an InterruptedException. That affords your thread the opportunity to check whether or not it still should be running.

How to stop and resume thread safely in Java?

I have running thread that I would like to stop and later on resume at some point. I learned not to use stop() etc. as these are deprecated and got to this code below that seems to stop thread successfully. It simply exits run method. Now, how can I restart it? If I call start() method it says that thread is still running, so would directly calling run() do in this situation? Would it cause any problems? BTW this is for Android app if that makes any difference.
private volatile stopThread;
public void stopButton() {
// this is called when button is clicked
// and thread is already started and running
stopThread= true;
}
public void run() {
while (!stopThread) {
// do something here
}
stopThread=false;
}
EDIT: its a timer that starts when thread is started, then can be paused and started again. So timer is a class containing Thread object (I already extend the class with SurfaceView).
The only safe way to stop and resume a thread safely is to add code at the relevant points in the thread's body to deal with it. (Don't use the deprecated Thread stop / pause / resume because they are fundamentally unsafe.)
Stop without resumption is relatively simple, using either an application-specific flag, or the Thread.interrupt() mechanism. The latter is probably better because some of Java's synchronization and IO APIs are interrupt-aware. However, you do run against the problem that a lot of existing libraries are not interrupt aware, or don't deal with InterruptedException properly.
Stop with resumption is more tricky. You'll need to create your own class something like this:
public class PauseControl {
private boolean needToPause;
public synchronized void pausePoint() {
while (needToPause) {
wait();
}
}
public synchronized void pause() {
needToPause = true;
}
public synchronized void unpause() {
needToPause = false;
this.notifyAll();
}
}
and add calls to myPauseControl.pausePoint() at relevant points throughout your the thread's code. Note that this won't allow you to pause IO, or activity in "child" threads, and it will only pause at points in your code where you call the pausePoint method. Also you need to beware of creating problems by pausing the thread while it holds locks on something else, or while something else is waiting for it to respond.
The Java 1.4 docs explained why and gave alternatives to the various deprecated Thread methods, including suspend() and resume() by using wait() and notify() instead.
Look for the heading What should I use instead of Thread.suspend and Thread.resume? about halfway down the page.
The stop() method of Thread class is deprecated and unsafe for use, because stopping a Thread causes it to unlock all monitors that it had locked. This has damaging consequences, because any of the Objects (previously protected by monitors) in an inconsistent state may now be viewed by other threads in an inconsistent state. This behavior may be subtle and difficult to detect.
You never invoke the run() method directly and if you stop the Thread using your volatile variable approach, the Thread would have TERMINATED. In order to start the Thread perform new Thread().start() again.

Do Java Threads need any cleanup?

I see that all the stop and destroy and anything else that deals with cleanup methods have been deprecated.
If I have a new Thread() or a class that extends Thread running, do I need to do anything in its run() method other than let it get to the end of regular execution? Or is there a background mechanism that understands that the Thread has run through all its tasks and can be destroyed?
When you call start() on your thread, native mechanism in JVM close to the operating system are starting your thread, eventually executing run(). When run() finishes, JVM takes care of everything.
You might be concerned about garbage collection or other resources cleanup. Of course if you open file/network connection inside a thread, it must be closed like everywhere else. Also the garbage collector, while analyzing live objects, takes into account objects referred from running threads. But the moment thread finishes, all the objects referenced by it (or by Runnable implementation passed to the thread) are eligible for garbage collection.
quick&dirty edit for exit method of Thread, as visible contextClassLoader is missing x.x
private void exit() {
if (group != null) {
group.remove(this);
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* Speed the release of some of these resources */
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
No cleanup needed. Once it finishes its task, the jvm will kill it.
The stop() method actually causes the Thread to throw an Error or Exception. The reason it is deprecated is this can happen anywhere in the code anything it modifies in a potentially unknown state. stop() is only really safe when stopping the current thread because you know when it will happen. BTW, You can catch the Error/Exception which would mean the Thread does not stop().
In any case, the result is the same, the run() returns (or fails to catch an Exception/Error). The stop() method triggers a special Error called ThreadDeath. The only thing special about it is that normally, an uncaught exception/error is printed, but this one is not. (And it doesn't have Error at the end of its name ;) You can change this behaviour if you wish.
When the Thread is no longer referenced, it can be cleaned up. (just like any other object) Note: you can hold a reference to it in another thread, preventing it from being cleaned up even thought it has finished.

Android IllegalThreadStateException in LunarLander

Just come to polishing my application and making it resume after the user has left. When the application restores I get an IllegalThreadStateException, which is quite annoying. This problem is present in the example google gives of Lunar Lander. Has anyone found a way to restore working when using surfaceView?
I believe this arises from a disparity in how the Surface and the Activity are handled. When you leave the LunarLander application the surface is destroyed (invoking surfaceDestroyed) but the Activity is only paused (invoking onPause). When the Activity is resumed the surface is created (invoking surfaceCreated) and it attempts to start the drawing thread again.
This means that creating the Thread happens with the Activity's lifecycle and destroying the thread happens with the SurfaceView's lifecycle, which do not always correspond, thus the IllegalThreadStateException. The solution would be to tie the thread to one lifecycle or the other, not both.
I think this thread proposes a possible solution, though I don't know if it works.
In my own test, I create the drawing thread in the surfaceCreated() method, and this solves the issue completely. This is my method implementation:
#Override
public void surfaceCreated(SurfaceHolder arg0) {
_thread = new DrawThread(getHolder());
_thread.setRunning(true);
_thread.start();
}
So in the code, when surfaceDestroyed() is called, it sets mRun to false and calls thread.join(). This causes the thread to complete and die. When the app is started again and surfaceCreated() is called, it calls thread.start(). This is invalid because the thread can not be started after it dies.
Two options to fix:
a) Start a new thread in surfaceCreated() - as above.
b) Or add a check in surfaceDestroyed() against Activity.isFinishing() to only end the thread if true. To do this, I surrounded the while(mRun) in the thread with another while loop that is only set to false if isFinishing() returns true.

Categories