Java: Why does this not get garbage collected? - java

Quick question about the theory of GCing. I have the following method. It runs, and exits the method. How come even after GC is run, the timer still exists and keeps "TICK"ing? I don't believe there's still a reference to timer or the timertask anymore after this method exists, so I'd expect the timer to be GCed and cause an exception. Please help me understand this concept.
Thanks,
jbu
private void startTimer()
{
Timer timer= new Timer();
TimerTask timerTask= new TimerTask()
{
#Override
public void run()
{
System.out.println("TICK");
}
};
timer.scheduleAtFixedRate(timerTask,
0,
500);
}

The Timer object actually schedules tasks to be executed in a background thread, so that background thread maintains a reference to the Timer (and the TimerTask), which prevents both from being garbage-collected.
Here is the appropriate quote from the docs:
After the last live reference to a
Timer object goes away and all
outstanding tasks have completed
execution, the timer's task execution
thread terminates gracefully (and
becomes subject to garbage
collection). However, this can take
arbitrarily long to occur. By default,
the task execution thread does not run
as a daemon thread, so it is capable
of keeping an application from
terminating. If a caller wants to
terminate a timer's task execution
thread rapidly, the caller should
invoke the the timer's cancel method.
So the condition that "all outstanding tasks have completed execution" is not satisfied, and the thread never terminates, so the Timer/TimerTask is never GC'd.

Because a Timer has a background thread that continues running:
Corresponding to each Timer object is
a single background thread that is
used to execute all of the timer's
tasks, sequentially. Timer tasks
should complete quickly. If a timer
task takes excessive time to complete,
it "hogs" the timer's task execution
thread. This can, in turn, delay the
execution of subsequent tasks, which
may "bunch up" and execute in rapid
succession when (and if) the offending
task finally completes.
Since it's a background thread, it continues until the JVM exits or it's stopped.
Update: a little more on this. A "background thread" is the same thing as a daemon thread -- named by analogy with a BSD daemon process. If you see the javadocs on Thread, you'll find:
Marks this thread as either a daemon
thread or a user thread. The Java
Virtual Machine exits when the only
threads running are all daemon
threads.
When your main terminates, all the user threads stop, leaving only daemon threads. The JVM then shuts down. For a good time — if short — call Thread.currentThread().setDaemon(true); from main.
Update: Ack. I had that almost right. You have to make the timer a daemon at construction time. (Did this change, or did I just have a brain failure?)
Anyway, here's example code:
import java.util.*;
class Chatter extends TimerTask {
public void run(){
System.err.println("Timer run.");
}
}
public class TryThread {
public static void main(String[] argv){
// If argument is true, only runs a few times.
Timer t = new Timer(false);
t.schedule(new Chatter(), 1L, 1L);
return ;
}
}

The timer's not being garbage collected because it's still running -- some other object (such as the thread scheduler) still has a reference to it, which was probably created inside scheduleAtFixedRate().

How do you know the GC ran? Garbage collection in general is not a deterministic thing, and it's definitely not triggered by method scope. It's not like C++ where you leave scope of a function and destructors fire. It will get around to collecting that memory if and when the GC feels like it.

Related

Java Timer scheduleAtFixedRate. How to make it so that calling .cancel will stop the timer only after the current iteration is done

I have a ReentrantReadWriteLock in my application. In the run method of the timertask, I do write lock and then call a function. After that I unlock:
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
lock.writeLock().lock();
function();
lock.writeLock().unlock();
}
}, 0, 1000); // prints 1 every 1second
The thing I'm worried about is what happens if this timer is canceled and the lock is not able to unlock. Is there a way o make it so that calling .cancel will stop the timer only after the current iteration is done.
Or is there another data structure I could use that allows me to, on a separate thread, run a task/function at a certain rate and be able to stop it such that all locks are released?
The javadoc tells that calling cancel() won't interrupt a currently running task, so you are safe on this part.
However, I recommand you to use ScheduledThreadPoolExecutor instead of Timer if you can.
It's more powerful, simpler to use, and more resilient to potential exceptions thrown by scheduled tasks.
With ScheduledThreadPoolExecutor, you may cancel a particular task by calling cancel(boolean mayInterruptIfRunning) on the Future returned when scheduling the task, or cancel all scheduled tasks by terminating the scheduler (see shutDown + awaitTermination methods).
If you only need a single thread working on the tasks, you can do so.
I also strongly recommand enclosing lock acquisition and release into a try...finally block.
This will make sure that, whenever problem occurs inside the task, the lock will always be released properly.
Otherwise, as you have well observed, a problem in the task will prevent the lock from being released.

Terminate Runnable

I have a task executor which takes runnable as a task. I am starting a timer before calling runnable.run() method and stopping it when the runnable finished. I want to terminate the execution of run() method from the executor itself if the timer exceeds the time limit. I do not know what user will implement in run().
TaskExecutor.add(new Runnable () {
#Override
public void run() {
System.out.println("This is test job");
}}
);
This is how the user adds a new task. Every task runs in the same thread.
Edit
This task executor will act as a service to users. And because creating threads are expensive operation and requires native OS calls, I am trying to avoid them. Otherwise I would call Thread.interrupt() at some point. But I just want to know if there is a way to terminate the run() method from a parent object. Terminate means to stop something abruptly. As how we terminate processes in OS task manager.
How tasks are executed
while (jobQueue.isEmpty()) {
for (Job job : jobQueue) {
long startTime = System.currentTimeMillis();
job.run();
//There is a separate thread which checks
//for timeout flags by comparing the startTime
//with the current time. But all tasks are
//executed in the same thread sequentially. I
//only want to terminate single jobs that are
//timed out.
}
}
you can check condition for your timer,if timer exceeds you can interrupt your thread like-
Thread.currentThread().interrupt();
It will stop your current Thread.
I just want to know if there is a way to terminate the run() method from a parent object.
You can't really terminate a method, and you can't really do anything from an object.
It's often convenient to say "this object does X," or "this method does Y," but objects and methods don't really do anything. When you're talking about multi-threaded code, it's important to realize that everything your program does is done by threads. Methods are just the instructions that tell threads what to do, and objects are what the threads do it to.
You can interrupt a thread, which is only a good idea if the thread is designed to gracefully handle the interrupt; and you can terminate a thread, which basically is never a good idea.
Threads should always cooperate with one another. You need to provide a means by which your program can politely ask the client-provided callback to abort its work and return early. If the client code does not respect your request (i.e., if the client code does not cooperate), that's the client programmer's fault for not obeying your guidelines.
The simplest way to do it would be to simply expose some static boolean method that the client can periodically check to see whether it's time to abort.

Why my thread did not die?

public void run() {
assignPlayer();
for(int i = 0; i < numPlayers; i++) {
PlayerListener listener = new PlayerListener(fromPlayer.get(i), this, i);
new Thread(listener).start();
}
return;
}
I am implementing a socket game. Every game has 2 players, and every game is given its own thread. the above run method assigns PlayerListener(which is a Runnable object) to each player for listening their incoming outputstream and calls some method from the game object if there is action to perform. Everything runs fine, but I was thinking about when will my game thread dies, so I intentionally set "return" after the PlayerListener assignment is finished ( but I think after the assignment is finished, there will be no statement so the run method will run anyway ). Anyway, my game is still running, shouldn't my thread dies and my game object dies along with it?
It is because the PlayerListener objects still calling the game object's method from time to time so the object does not get garbage collected??
I read the post When does a Java Thread reach the 'Die' State. It states that "If the run() method returns", so I was curious...
so I intentionally set "return" after the PlayerListener assignment is finished
Your return; is extraneous since it's at the end of the method. The method would return without it. The only time a thread will wait for the threads it forks is if you specifically call thread.join() on each of the threads.
Anyway, my game is still running, shouldn't my thread dies and my game object dies along with it?
The threads that you fork are most likely non-daemon threads. Daemon threads exit when the JVM exits but the JVM waits for all non-daemon threads to exit on their own. When you fork threads they take on the daemon status of the thread that forked them. If you want these threads to quit once the run() method finishes then say something like:
Thread thread = new Thread(listener);
// make sure the threads will be killed when all other threads finish
thread.setDaemon(true);
thread.start();
I read the post When does a Java Thread reach the 'Die' State. It states that "If the run() method returns", so I was curious...
Right. If you are in a thread's run() method, then that thread will finish if the run() method finishes. However, again, the threads that are forked in the loop will keep the application running unless they are specifically set as being daemon threads.
The "return;" statement does nothing, since it's at the end of a void method (and the compiler automatically adds code to a void method as if there were a "return;" statement there).
You haven't really asked a clear question. Are you asking why the program doesn't terminate?
You didn't explain how this particular "run()" method gets called. Only if it is the run() method of the thread itself, and called as part of the thread starting, will its return cause the thread to die.
Furthermore, the process will not die as long as there is at least one non-daemon thread running.
All in all, you have provided a patchwork of partial information, and a patchwork of partial questions. Connecting those two patchworks is beyond the abilities of Agatha Christie, let alone anyone with perfect knowledge of Java, let alone people on this site.

Exception when losing a thread

I start two threads with a Timer and TimerTasks
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
doSomething();
}
};
Calendar start = Calendar.getInstance();
timer.scheduleAtFixedRate(task, start.getTime(),
1000 * 60 * 60);
Now sometimes the second thread stops. Is there a possibility to observe the thread perhaps for sending a mail when this thread stops, maybe by a third thread that looks for the second thread?
You need to keep the reference to your Timer alive - if the Timer is garbage collected, the thread will stop. From the docs:
After the last live reference to a
Timer object goes away and all
outstanding tasks have completed
execution, the timer's task execution
thread terminates gracefully (and
becomes subject to garbage
collection). However, this can take
arbitrarily long to occur. By default,
the task execution thread does not run
as a daemon thread, so it is capable
of keeping an application from
terminating. If a caller wants to
terminate a timer's task execution
thread rapidly, the caller should
invoke the timer's cancel method.
That may not be the problem, but it's the most likely cause. I assume if you can keep the thread alive, you don't need anything checking it?
I'd suggest adding a Thread#setDefaultUncaughtExceptionHandler to your program. You can have this log/email/etc.. While having a catch(Throwable) is better design, having an uncaught exception handler can handle any cases you miss.

Timer vs Thread primitive in Java

Has anyone observed that creating a thread that does work in a while(true) loop with a Thread.sleep(t) appears to consume more CPU than creating a Timer in Java with a wakeup of t? Anyone with JVM expertise know why this is? I've only really tried this on Windows and Linux x86.
According to the Javadoc for the Timer class, there's a background thread that does the work:
Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread. This can, in turn, delay the execution of subsequent tasks, which may "bunch up" and execute in rapid succession when (and if) the offending task finally completes.
How are you observing CPU usage? Have you tried a JVM profiler?

Categories

Resources