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的主要内容,如果未能解决你的问题,请参考以下文章
Java 开发新选择?Apache NetBeans IDE 9.0 正式发布
netbeans 6.9运行不了,提示一个或多个项目未正确设置目标服务器