48

在 NetBeans 中,有一个新提示:Thread.sleep call in loop。

问题 1:循环睡眠如何/何时会成为问题?

问题2:如果有问题,我应该怎么做?

更新:问题 3:这是一些代码。在这种情况下告诉我是否应该在循环中使用其他东西而不是 Thread.Sleep。简而言之,这是由侦听客户端 TCP 连接的服务器使用的。如果达到与客户端的最大会话数,则在此处使用睡眠。在这种情况下,我希望应用程序等到空闲会话可用。

public class SessionManager {
    private static final int DEFAULT_PORT = 7500;
    private static final int SLEEP_TIME = 200;
    private final DatabaseManager database = new DatabaseManager();
    private final ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT);

public SessionManager() throws IOException, SQLException
{
}

public void listen()
{
while (true)
    if (Session.getSessionCount() < Session.getMaxSessionCount())
        try
        {
             new Thread(new Session(database, serverSocket.accept())).start();
        }
        catch (IOException ex) { ex.printStackTrace(); }
    else
        try
        {
            Thread.sleep(SLEEP_TIME);
        }
        catch (InterruptedException ex) { ex.printStackTrace(); }
}

public static void main(String[] args) throws IOException, SQLException
{
new SessionManager().listen();
}
}
4

4 回答 4

22

在循环中调用 sleep 通常会导致性能下降。例如:

while (true) {
    if (stream.available() > 0) {
       // read input
    }
    sleep(MILLISECONDS);
}

如果 MILLISECONDS 太大,那么这段代码将需要很长时间才能意识到输入可用。

如果 MILLISECONDS 太小,那么这段代码将浪费大量系统资源检查尚未到达的输入。

循环中的其他用途sleep通常也是有问题的。通常有更好的方法。

如果这是一个问题,我应该怎么做?

发布代码,也许我们可以给你一个明智的答案。

编辑

IMO,解决问题的更好方法是使用ThreadPoolExecutor.

像这样的东西:

public void listen() {
    BlockingQueue queue = new SynchronousQueue();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, Session.getMaxSessionCount(), 100, TimeUnit.SECONDS, queue);
    while (true) {
        try {
            queue.submit(new Session(database, serverSocket.accept()));
        } catch (IOException ex) { 
            ex.printStackTrace();
        }
    }
}

这会将执行程序配置为与您的代码当前的工作方式相匹配。您还有许多其他方法可以做到这一点;请参阅上面的 javadoc 链接。

于 2010-08-21T03:47:37.700 回答
5

正如其他人所说,这取决于使用情况。合法的用途是设计为每 10 秒执行一次操作的程序(但不是那么关键,需要精确的时间)。我们有很多这样的“实用程序”,每隔几分钟就会导入数据和其他类似任务。这是执行这些任务的一种简单方法,我们通常会将睡眠间隔设置为非常低并使用计数器,以便程序保持响应并轻松退出。

int count = 0;
while (true) {

    try {
        // Wait for 1 second.
        Thread.sleep(1000);
    }
    catch (InterruptedException ex) {}

    // Check to see if the program should exit due to other conditions.
    if (shouldExit())
        break;

    // Is 10 seconds up yet? If not, just loop back around.
    count++;
    if (count < 10) continue;

    // 10 seconds is up. Reset the counter and do something important.
    count = 0;
    this.doSomething();
}
于 2011-07-14T20:49:55.603 回答
4

我想我遇到了一种完全合法的sleep()循环使用方法。

我们在服务器和客户端之间有单向连接。因此,当客户端想要实现与服务器的异步通信时,他会向服务器发送消息,然后定期轮询服务器的一些响应。需要有一些超时间隔。

Response resp = null;
for (int i = 0; i < POLL_REPEAT && resp == null; i++) {
    try {
       Thread.sleep(POLL_INTERVAL);
    } catch (InterruptedException ie) {
    }
    resp = server.getResponse(workflowId);
}

POLL_REPEAT* POLL_INTERVAL~ TIMEOUT 间隔

于 2012-07-17T14:47:48.847 回答
1

循环睡眠如何/何时会成为问题?
人们有时会使用它来代替适当的同步方法(如等待/通知)。

如果这是一个问题,我应该怎么做?
取决于你在做什么。尽管我很难想象这样做是最好的方法的情况,但我想这也是可能的。

您可以查看Sun关于此主题的并发教程。

于 2010-08-21T00:43:14.477 回答