如何保证在EDT上运行ScheduledExecutorService?

时间:2014-05-11 18:53:54

标签: java swing thread-safety

在处理动画和更新游戏计时器时,我读到任何与GUI相关的活动都应该在EDT上运行,包括重新绘制屏幕。我使用单个ScheduledExecutorService来更新和绘制游戏(使用活动渲染)。服务的初始计划(这是一个implements Runnable的嵌套类)在这样的调用中完成:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            ex.schedule(new UpdatingService(), 1, TimeUnit.MILLISECONDS);
        }
    });

我认为这会使服务在EDT上运行,但添加System.out.println(SwingUtilities.isEventDispatchThread());证明它不是。

我做了一些搜索,发现this帖子提到了启动EDT 里面的计时器。我尝试了这个,它确实有效。但是,像这样嵌套线程似乎不是一个好主意。

那么,像这样嵌套线程并不像看起来那么糟糕吗?如果这是一个坏主意,那么确保{1}在EDT上运行的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

在您的代码中:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            ex.schedule(new UpdatingService(), 1, TimeUnit.MILLISECONDS);
        }
    });

此处在EDT上执行的唯一代码是ex.schedule调用。稍后由调度程序调用的代码,例如new UpdatingService()将在调度程序内部的线程上运行,该线程不是EDT,而是由Executors.newSingleThreadScheduledExecutor调用创建的某个线程

也许我要做的就是让你的调度程序安排一个更新方法(也许你的更新服务),然后通过invokeLater将调用放到EDT上。

例如:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(new Updater(), 1, TimeUnit.MILLISECONDS);
...
class Updater extends Runnable {
    @Override
    public void run() {
      // invoke the EDT via Swing Utilities here.     
    }
}

这是我最好的建议,而不会看到你的其余代码在做什么。