我需要反复执行一项影响GUI相关和非GUI相关对象的任务。需要注意的是,如果在触发下一个计时器事件时前一个任务尚未完成,则不应执行任何操作。 我最初的想法是将SwingTimer与javax.swing.SwingWorker对象结合使用。一般设置看起来像这样。
class
{
timer = new Timer(speed, this);
timer.start();
public void actionPerformed(ActionEvent e)
{
SwingWorker worker = new SwingWorker() {
@Override
public ImageIcon[] doInBackground() {
// potential long running task
}
@Override
public void done() {
// update GUI on event dispatch thread when complete
}
}
}
我用这种方法看到的一些潜在问题是:
1)如果工作人员在计时器触发下一个ActionEvent之前尚未完成,则多个SwingWorkers将处于活动状态。
2)SwingWorker只设计执行一次,因此持有对worker的引用并重用(不是?)一个可行的选项。
有没有更好的方法来实现这一目标?
答案 0 :(得分:1)
您是否考虑过使用简单的Java Timer和ReadWriteLock来确定当计时器再次触发时任务是否正在运行?在这种情况下,你可以简单地摆脱那个特定的迭代并等待下一个迭代。
答案 1 :(得分:1)
为什么使用定时器?保持“工人”一直运行会更简单,只要任务花费的时间太少,就可以通过sleep()暂停。您仍然可以使用以下内容更新事件派发线程中的内容:
Thread background = new Thread(new Runnable() {
public void run() {
while ( ! stopRequested ) {
long start = System.currentTimeMillis();
// do task
long elapsed = start - System.currentTimeMillis();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// update UI
}
});
if (elapsed < tickTime) {
Thread.sleep(tickTime - elapsed);
}
}
}
}.start();
答案 2 :(得分:1)
对于(1),scheduleAtFixedRate()
上的ScheduledThreadPoolExecutor
方法可能有用。来自javadocs:
如果执行此任务的时间超过其周期,则后续执行可能会延迟,但不会同时执行。
对于(2),看起来您可以定义SwingWorker
的子类并为每次迭代构造子类的新实例,而不是实例化匿名子类。