如何避免使用Thread.Sleep

时间:2011-01-18 22:13:00

标签: java multithreading sleep

在我下载最新版本的Netbeans之前,我从未想过使用Thread.Sleep。 Netbeans现在警告你不要使用Thread.Sleep。所以我对这个主题进行了一些研究,发现人们说你只需要使用Thread.Sleep进行调试/测试,如果你在任何时候使用它,那么你的代码写得很差。

所以我的问题是如何在以下情况下继续使用Thread.Sleep。

我编写了一个与另一个应用程序连接的服务器应用程序。服务器有两个线程:

  1. 处理来自套接字的数据并发送回其他信息或仅发送简单的信息。

  2. 这是主线程。在开始套接字线程后,它将进入无限循环。在这个while循环中,我检查以确保套接字线程仍处于活动状态,并且用户没有要求通过TrayIcon接口退出应用程序。然后我睡觉并继续循环。

  3. 使用此应用程序,TrayIcon是唯一的UI。

    以下是我引用的代码段:

    // continues running as long as the exitth file is not present and 
    // the tray icon is not in a safe to exit status.
    
    while(doNotExit())
    {
    
        if (getPrimaryThread() == null || !getPrimaryThread().isAlive())
            resetsThreadAndSocket();
    
        try
        {
            // check to see if the socket threads are still active, if not create new ones.
            if ((getPrimaryThread() == null || !getPrimaryThread().isAlive()))       
                createSocketThread();
    
            // check right before sleeping that the user does not want to exit.
            if(getTrayIcon().isExiting())
                break;
    
            // puts the main Thread to sleep for 3 seconds
               Thread.sleep(3000);
        }
        catch(SQLException ex)
        {
            _log.error(ex.getMessage(), ex);
            restartDatabase();
        }
    }
    

4 个答案:

答案 0 :(得分:6)

在大多数情况下,'首选'方法是使用JavaSE中内置的ScheduledExecutorService来执行周期性任务,而不是每次使用while循环和Thread.Sleep()时自己重新实现它。

你的例子本身并没有错。从Java 5开始,该语言现在具有更强大的支持。

答案 1 :(得分:3)

而不是你的Thread.sleep(3000)做:

getPrimaryThread().join(3000)

这将等待线程退出3秒钟。

答案 2 :(得分:2)

您应该考虑将事件监听器附加到托盘图标而不是轮询其状态。这样,您不需要额外的线程来监控。

如果由于某种原因你不能这样做,你仍然可以取消额外的线程,因为Timer类可以等你。

答案 3 :(得分:1)

你似乎是偏执的,某些条件(可能是RuntimeException或Error?)会导致你的套接字线程死掉。理想情况下,您可以设计您的套接字线程,以保护自己免受崩溃。以下示例创建一个只能因JVM错误或线程中断而中断的循环:

public void run() {
    while(!Thread.currentThread.isInterrupted()) {
        try {
            //you application logic
        } catch (RuntimeException e) {
           //log uncaught exception
        }
    }
}

为了关闭应用程序,你可以将一个监听器附加到包含对SocketThread的引用的TrayIcon,并且可以通过简单地中断它来阻止它。

socketThread.interrupt();

我将留下如何将ActionListener添加到TrayIcon中。