【问题标题】:How does one guarantee that an ScheduledExecutorService is running on the EDT?如何保证 ScheduledExecutorService 在 EDT 上运行?
【发布时间】:2014-05-12 03:01:47
【问题描述】:

在为游戏制作动画和更新计时器时,我了解到任何与 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 帖子中提到了在 inside 计时器中启动 EDT。我试过了,它确实有效。但是,像这样嵌套线程似乎不是一个好主意。

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

【问题讨论】:

  • "我做了一些搜索,发现这篇文章提到在计时器内启动 EDT。" => 这就是要走的路。
  • 确保代码在事件调度线程上执行的最简单方法是使用javax.swing.Timer(不是 java.util.Timer)而不是 ScheduledExecutorService。

标签: java swing thread-safety


【解决方案1】:

在您的代码中:

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

这是我最好的建议,而无需了解您的其余代码在做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 2021-08-18
    • 2014-04-14
    相关资源
    最近更新 更多