我需要重复执行一个同时影响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)如果一个工作者在定时器触发下一个SwingWorkers之前还没有完成,则多个ActionEvent将被激活。
2) SwingWorker被设计为只执行一次,因此保持对worker的引用并重用(不是吗?)一个可行的选择。
有没有更好的方法来实现这一点?
发布于 2010-04-08 14:17:41
对于(1),ScheduledThreadPoolExecutor上的scheduleAtFixedRate()方法可能很有用。在javadoc中:
如果此任务的任何执行时间超过其周期,则后续执行可能会延迟开始,但不会并发执行。
对于(2),看起来您可以定义SwingWorker的一个子类,并为每次迭代构造该子类的新实例,而不是实例化一个匿名子类。
发布于 2010-04-07 23:16:53
您有没有考虑过使用一个简单的Java定时器和一个ReadWriteLock来确定当定时器再次触发时任务是否正在运行?在这种情况下,您可以简单地退出该特定迭代,并等待下一次迭代。
发布于 2010-04-08 07:58:17
你为什么要用计时器?让“worker”一直运行会更简单,只要任务完成的时间太短,就会通过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();https://stackoverflow.com/questions/2593605
复制相似问题