简体   繁体   English

如何避免使用Thread.Sleep

[英]How to avoid use of Thread.Sleep

I never gave the use of Thread.Sleep much thought, until I downloaded the latest version of Netbeans. 在我下载最新版本的Netbeans之前,我从未想过使用Thread.Sleep。 Netbeans now warns you not to use Thread.Sleep. Netbeans现在警告你不要使用Thread.Sleep。 So I did some research on the topic and found people stating that you only need to use Thread.Sleep for debugging/testing purposes and that if you use it at any other time you have poorly written code. 所以我对这个主题进行了一些研究,发现人们说你只需要使用Thread.Sleep进行调试/测试,如果你在任何时候使用它,那么你的代码编写得很糟糕。

So my question is how can I keep from using Thread.Sleep in the following situation. 所以我的问题是如何在以下情况下不使用Thread.Sleep。

I have written a server application that interfaces with another application. 我编写了一个与其他应用程序连接的服务器应用程序。 The server has two threads: 服务器有两个线程:

  1. Handles the data coming over the socket and sends back other information or just plain acknoledgements. 处理来自套接字的数据并发回其他信息或仅发送简单的知识。

  2. This is the main thread. 这是主线程。 After kicking off the socket thread it going into an indefinite while loop. 在开始套接字线程后,它将进入无限循环。 Within this while loop I check to make sure the socket thread is still active and that the user hasn't asked to exit the application via a TrayIcon interface. 在这个while循环中,我检查以确保套接字线程仍处于活动状态,并且用户没有要求通过TrayIcon接口退出应用程序。 Then I sleep and continue this while loop. 然后我睡觉并继续循环。

With this application, the TrayIcon is the only UI. 使用此应用程序,TrayIcon是唯一的UI。

Here is the snippet I'm referencing: 这是我引用的片段:

// 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();
    }
}

The 'preferred' method in most cases would be to use the ScheduledExecutorService built into JavaSE for performing a periodic task, rather than reimplementing it yourself every time using a while loop and Thread.Sleep() . 在大多数情况下,“首选”方法是使用JavaSE中内置的ScheduledExecutorService来执行周期性任务,而不是每次使用while循环和Thread.Sleep()重新实现它。

There's nothing wrong per-se with your example. 你的例子本身并没有什么不妥。 The language just now has a much more robust support for doing that built into it as of Java 5. 从Java 5开始,这种语言现在拥有更强大的支持。

Instead of your Thread.sleep(3000) do: 而不是你的Thread.sleep(3000)做:

getPrimaryThread().join(3000)

This will wait for the thread to exit for 3 seconds. 这将等待线程退出3秒。

You should consider attaching an event listener to your tray icon instead of polling its state. 您应该考虑将事件侦听器附加到托盘图标而不是轮询其状态。 That way you won't need an extra thread just for monitoring. 这样你就不需要额外的线程来监控了。

If you can't do that for some reason, you can still do away with the extra thread as the Timer class can do the waiting for you. 如果由于某种原因你不能这样做,你仍然可以取消额外的线程,因为Timer类可以等你。

You seem to be paranoid that some condition (maybe a RuntimeException or Error?) is going to cause your socket Thread to just die. 你似乎是偏执的一些条件(可能是RuntimeException或错误?)将导致你的套接字线程死亡。 Ideally, you would design your Socket Thread such that it protected itself from crashing. 理想情况下,您可以设计您的套接字线程,以保护自己免受崩溃。 The following example creates a loop that can only be broken as a result of a JVM Error or Thread interrupt: 以下示例创建一个只能由于JVM错误或线程中断而中断的循环:

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

In order to shutdown the application, you would attach a listener to the TrayIcon which contained a reference to the SocketThread and could stop it by simply interrupting it. 为了关闭应用程序,你可以将一个监听器附加到包含对SocketThread的引用的TrayIcon,并且可以通过简单地中断它来阻止它。

socketThread.interrupt();

I'll leave figuring how to add an ActionListener to a TrayIcon up to you. 我将留下如何将ActionListener添加到TrayIcon中。

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

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