简体   繁体   English

为什么Java Timer线程消失了?

[英]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. CloseTask类中run()方法的CloseTask是循环运行,直到state变量从OPEN状态更改为其他状态为止。 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. 但是,定时器线程会间歇性地消失,而state仍然等于OPEN ,我知道每隔5分钟打印出当前正在运行的线程的所有线程ID。

So my questions: 1) The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. 所以我的问题是:1)我能想到的唯一解释是CloseTask对象CloseTask未捕获的异常。 Is that correct? 那是对的吗? 2) If 1) is correct why isn't my try catch block catching these exceptions? 2)如果1)是正确的,为什么我的try catch块不捕获这些异常? 3) If 1) is correct is there a way to catch these exception that slip through uncaught? 3)如果1)正确,是否有办法捕获这些未捕获的异常?

Thanks for any insight into this issue. 感谢您对此问题的任何见解。

You're creating a Timer instance, but not making sure that it doesn't get garbage collected. 您正在创建一个Timer实例,但不能确保它不会垃圾收集。

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). 在最后一个对Timer对象的实时引用消失并且所有未完成的任务均已完成执行之后,计时器的任务执行线程会正常终止(并受到垃圾回收的影响)。

So basically, you need to hold on to the reference to the Timer you created instead of just using a local variable. 因此,基本上,您需要保留对创建的Timer的引用,而不仅仅是使用局部变量。

The boolean you are passing in tells whether or not the thread created will be daemon . 您传入的布尔值告诉创建的线程是否将是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. 由于在应用程序中运行的唯一非守护程序线程是主线程,因此在main方法完成后,它将立即停止。

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. 正如Jon Skeet所提到的,如果没有活动线程引用Timer并且任务已完成,那么将完成一些完成操作,但是如果它是守护进程并且main方法已完成,则可能无法正常退出。 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. 如果调用方想快速终止计时器的任务执行线程,则调用方应调用计时器的cancel方法。

To answer your question 回答你的问题

The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. 我能想到的唯一解释是CloseTask对象引发了未捕获的异常。 Is that correct? 那是对的吗?

If the JVM kills a non-daemon thread, it won't throw any exception. 如果JVM杀死了非守护程序线程,它将不会引发任何异常。 So you won't really know that it happened. 这样您就不会真正知道它发生了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM