我的程序可视化物理模拟(基本上)。现在,它可以工作,但可能会变得非常迟钝,而且我想我知道为什么 - 在事件线程上完成了太多(读取:全部)计算。
当按下“播放”按钮时,将创建一个 Swing Timer
,它会定期唤醒并调用 updateTime()
- 目前一切顺利。问题在于 updateTime()
遍历每个与时间相关的对象,并告诉它按适当的时间将自身向前传播(无论是实际流逝的时间,还是每次滴答的任意时间单位)。这些计算,以及后续的 GUI 更新,都在事件调度线程上进行。
所以,我想尽可能多地卸载这种计算,我认为 SwingWorker
是可行的方法,但我不确定如何将它们用于现有的代码。我不能让现有的类扩展 SwingWorker
,因为它们中的许多已经扩展了其他类。
到目前为止,我最好的想法是为每个要实现的时间相关对象创建一个接口(interface)。该接口(interface)将指定 2 个方法,calcUpdateTime()
和 drawUpdateTime()
。我会将他们当前的每个 updateTime()
方法拆分为物理计算(到 calc_
)和 GUI 更新(到 draw_
)。然后我将只创建一个 SwingWorker 类,它在构造函数中采用 TimeDependant
对象,并且它的 doInBackground
将调用 calcUpdateTime
和 done
会调用 drawUpdateTime
。这样我就可以替换所有出现的
myObj.updateTime(currentTime);
与
new MySwingWorker(myObj, currentTime).execute();
我想通过 SO 运行这个想法,因为它感觉不太对,而且它想避免重构整个项目只是为了发现我开始时的想法不好。另外,每次 tick 可能创建几十个 MySwingWorker
不是一个坏主意吗?
感谢您阅读到这里。
最佳答案
你是对的,没有必要为每个 worker 的每个 tick 调用 SwingWorker.execute()
,因为你将创建和销毁很多你实际上不需要的线程需要。
但是,使用 SwingWorker
仍然是一个好主意,只是因为它为您提供了一种简单的方法来分离需要在后台运行的代码(您对 SwingWorker 的实现。 doInBackground()
) 从需要在 Swing 中运行的代码中提取,以便之后更新 GUI(您的 SwingWorker.done()
实现)。
与其使用 javax.swing.Timer
或 java.util.Timer
,我建议使用 java.util.concurrent.ScheduledThreadPoolExecutor
.基本上,它可以做 java.util.Timer
可以做的所有事情,除了它还让您有机会控制有多少线程在后台工作,如何处理抛出的异常后台线程等。
关于java - 使 GUI 更具响应性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2286837/