为什么这段代码会冻结我的Swing应用程序? Swing组件与InfiniteLoop线程位于一个单独的线程中。如果我在每次打印之前在run()方法中引入sleep,那么程序运行正常。有人有任何线索吗?
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI(); // <-- creates the swing frame and component
}
});
Thread t = new Thread(new InfiniteLoop());
t.start();
}
public class InfiniteLoop implements Runnable
{
private static Logger logger = Logger.getLogger(InfiniteLoop.class);
public void run()
{
while(true)
{
log.info("test");
}
}
}
答案 0 :(得分:3)
这里的答案与Java的线程调度实现(或者更确切地说,是平台的Java线程调度实现的细节)有关。大多数Java线程实现最终运行一个给定的线程(在给定的优先级),直到线程进入等待状态。然后运行该优先级中的下一个线程,等等......请注意,JVM规范没有指定确切的行为 - 这取决于JVM实现者的决定。
您可能需要考虑降低工作线程的优先级,而不是将睡眠插入工作线程。睡觉线程会起作用,但要记住这样做会很麻烦,并且它会迫使工作线程花费更长的时间来做事情。如果您最终插入睡眠调用,请执行0毫秒(这足以释放线程,但如果没有其他线程处于活动状态,则应立即返回执行)。
这里有an article描述了这一点。
作为一种潜在的改进:invokeLater()调用最终可能会将runnable放在一个永远不会出队的队列中,因为你的后台线程占用了所有的CPU。一个有趣的实验是将后台线程的启动移动到Runnable中 - 这将使EDT有机会在后台线程开始消耗CPU之前进行初始化。
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI(); // <-- creates the swing frame and component
Thread t = new Thread(new InfiniteLoop());
t.start();
}
});
}
甚至:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Thread t = new Thread(new InfiniteLoop());
t.start();
createAndShowGUI(); // <-- creates the swing frame and component
}
});
}
我实际上对这个结果很感兴趣(实际测试不够兴趣,但是:-))。我在网上看到的一些参考文献说默认情况下EDT以更高的优先级运行(在这种情况下,EDT本身不应该出现饥饿)。如果从EDT内部启动后台线程,Swing界面是否仍然保持响应?