在NetBeans中,有一个新提示: Thread.sleep在循环中调用。
问题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();
}
}
答案 0 :(得分:22)
在循环中调用睡眠通常会导致性能不佳。例如:
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链接。
答案 1 :(得分: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();
}
答案 2 :(得分:2)
如何/何时在循环中睡觉会有问题?
人们有时会使用它代替适当的同步方法(如wait / notify)。
如果这是一个问题,我该怎么办呢?
取决于你在做什么。虽然我很难想象这样做是最好的方法,但我想这也是可能的。
您可以查看有关此主题的Sun's concurrency tutorial。
答案 3 :(得分:2)
我认为我在循环中遇到了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
〜超时间隔