在为游戏制作动画和更新计时器时,我了解到任何与 GUI 相关的 Activity 都应该在 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。我试过这个,它确实有效。但是,像这样嵌套线程似乎不是一个好主意。

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

最佳答案

在您的代码中:

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.
    }
}

这是我最好的建议,没有看到您的其余代码在做什么。

关于java - 如何保证 ScheduledExecutorService 在 EDT 上运行?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23596620/

10-11 15:19