NetBeans / Java / 新提示:在循环中调用 Thread.sleep

Posted

技术标签:

【中文标题】NetBeans / Java / 新提示:在循环中调用 Thread.sleep【英文标题】:NetBeans / Java / New hint: Thread.sleep called in loop 【发布时间】:2011-04-01 22:25:53 【问题描述】:

在 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();


【问题讨论】:

【参考方案1】:

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

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

您可以在此主题上查看Sun's concurrency tutorial。

【讨论】:

人们有时也会在读取循环中将它与测试 available() 结合使用,此时他们应该只是阻塞读取而不是浪费时间和空间。 一种用法是目录清理器,它删除超过某个时间段的文件。在第一次运行之后,我们知道哪个是最旧的文件,以及它会变得“太旧”的确切时间,因此我们可以在这段时间内休眠。 @Jesse - 一个预定的线程池执行器可能会更好。【参考方案2】:

在循环中调用 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 链接。

【讨论】:

java.util.Timer 和周期性 TimerTask 怎么样? @Core - 这取决于你如何使用它。如果你只是用它来实现 sleep() 的等价物,你会遇到与使用 sleep() 相同的问题。【参考方案3】:

正如其他人所说,这取决于使用情况。一个合法的用途是一个设计为每 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();

【讨论】:

在大多数情况下,使用调度的线程池执行器在技术上会更好,但是当你只是在编写一些快速而肮脏的东西时,这有时就太过分了。 @mjaggard 可以说我目前有一个带有循环的线程,里面有一个睡眠。它正在执行内务管理任务,例如清除不再相关的旧数据。与仅仅拥有一个长期存在的、主要是空闲的线程相比,使用调度的线程池执行器会给代码增加不必要的复杂性。对于休眠的长寿命/空闲线程,上下文切换惩罚可以忽略不计。除了删除“它不是一个好的做法”警告之外,调度线程池实际上给你带来了什么? 你写出每个的代码了吗?我怀疑预定的线程池执行器版本实际上可能更短,更易于阅读并且效率非常相似。【参考方案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 ~ 超时间隔

【讨论】:

如果您的 API 可能的话,一个更好的解决方案是使用阻塞 IO 方法,该方法一直等到有新数据可用。

以上是关于NetBeans / Java / 新提示:在循环中调用 Thread.sleep的主要内容,如果未能解决你的问题,请参考以下文章

如何向 NetBeans 添加新的 Java 组件?

如何增强NetBeans的智能提示功能

Java 开发新选择?Apache NetBeans IDE 9.0 正式发布

netbeans 6.9运行不了,提示一个或多个项目未正确设置目标服务器

NetBeans 中的 Java Swing Jscrollpane

更改 C++ netbeans 项目中的主文件