while (true)
对您的资源有点苛刻,应该在那里暂停约 10 秒。这并不需要像股票价格行情一样准确和实时。
使用 Swing,规则是在事件调度线程上不做任何花费时间的事情。后台任务或其他长时间运行的操作永远不应在其上运行。
对于您的特定情况,这适用:
由于非 AWT 事件而必须更新 GUI 的程序:
例如,假设一个服务器程序可以从可能在不同机器上运行的其他程序获取请求。这些请求可以随时出现,它们会导致在某个可能未知的线程中调用服务器的方法之一。该方法如何更新 GUI?通过在事件调度线程中执行 GUI 更新代码。
所以我要做的是设置一个计划任务,每隔 10 秒检查一次 Internet 连接的可用性,从事件调度线程开始 - 这可能最好在你的main
方法中立即设置。另一方面,GUI 的更新应该发生在事件分派线程上。这是一个Runnable
可以对您的标签进行更新的建议。ConnectionChecker
后面我会解释。我们使用 a 执行它ExecutorService
并将超时设置为 5 秒。如果ConnectionChecker
在 5 秒内成功,则您已连接,否则您未连接。然后使用此结果更新事件分派线程JLabel
上SwingUtilities#invokeLater
的.
public static class Updater implements Runnable {
private final JLabel label;
private final ExecutorService executor;
/* constructor left out */
public void run() {
boolean connected = false;
Future<?> connHandle = executor.submit(new ConnectionChecker());
try {
connHandle.get(5, TimeUnit.SECONDS);
connected = true;
} catch (TimeOutException ex) {
/* connected = false; */
}
catch (InterruptedException ex) {
/* Let it be handled higher elsewhere */
Thread.currentThread().interrupt();
} catch (CancellationException ex) {
/* happens only if you actively cancel the Future */
} catch (ExecutionException ex) {
/* connected = false */
}
final boolean result = connected;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (result)
label.setText("online");
else
label.setText("offline");
}
});
}
}
现在我们必须在 main 方法中设置一个定期执行Updater
的方法,其中我们还创建了 JLabel 和 ExecutorService:
public static void main(String... args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
JLabel label = ...;
Updater updater = new Updater(label, executor);
executor.scheduleAtFixedRate(updater, 0, 10, TimeUnit.SECONDS);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//GUI initialization code
}
});
}
最后,让我们推理一下ConnectionChecker
。有很多方法可以做到这一点。一个快速而肮脏的解决方案是简单地获取一个可能会在未来几年内保留的网页 - www.google.com 怎么样。如果您(正确)连接到 Internet,则此查询将成功。否则,它最终会抛出一些异常。通过连接,下载应该在 5 秒内完成 - 如果不是,那么超时连接尝试是安全的。Updater
无论哪种方式,如果下载没有及时成功,您将收到一个异常。使用简单URLConnection
或类似的方式进行下载。