driftwood
driftwood

Reputation: 2109

Why are Java Timer threads disappearing?

I have code that schedules one-time tasks to execute and does this over and over. It looks something like this.

public static void main(String[] args) 
{
    while(true)
    {
    ....
    TimerTask closeTask = new CloseTask(cli);
    Timer timer = new Timer(true);
    timer.schedule(closeTask, (long) (iPeriod * 60 * 1000));
    ...
    }
}   
public class CloseTask extends TimerTask 
{
    Client client;
    CloseTask(Client in_client)
    {
        client = in_client;
    }
    public void run()
    {       
        try
        {           
            for(int iRetries = 0; state == OPEN; iRetries++)
            {                   
                logger.log_trade_line_grablock( "Thread " + Thread.currentThread().getId() + ": About to send message", true, true, true, true, true);
                client.send_mesg("close");
                logger.log_trade_line_grablock( "Waiting 5 seconds before retrying ", true, true, true, true, true);
                Thread.sleep(5000);
            }
        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }   
}

The intent of the run() method in the CloseTask class is to loop until the state variable changes from OPEN state to something else. However, intermittently the timer threads simply disappear, while state still equals OPEN, which I know by printing out all the thread ID's of the currently running threads every 5 minutes.

So my questions: 1) The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct? 2) If 1) is correct why isn't my try catch block catching these exceptions? 3) If 1) is correct is there a way to catch these exception that slip through uncaught?

Thanks for any insight into this issue.

Upvotes: 2

Views: 983

Answers (2)

John Vint
John Vint

Reputation: 40256

The boolean you are passing in tells whether or not the thread created will be daemon. If it is daemon, the thread will be stopped once all non-daemon threads are finished. Since the only non-daemon thread being run in your application is the main thread then it will immediately be stopped after the main method is completed.

As Jon Skeet mentioned there is some completion operations done if no live thread is referencing the Timer and the tasks complete, but if it's daemon and the main method completes, it may not exit gracefully. To continue the documentation

... 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.

To answer your question

The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?

If the JVM kills a non-daemon thread, it won't throw any exception. So you won't really know that it happened.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1501043

You're creating a Timer instance, but not making sure that it doesn't get garbage collected.

From the documentation:

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).

So basically, you need to hold on to the reference to the Timer you created instead of just using a local variable.

Upvotes: 2

Related Questions