문제

While working on the animation and updating timer for a game, I read that any activities relating to the GUI should be run on the EDT, including repainting the screen. I am using a single ScheduledExecutorService to update and draw the game (using active rendering). The initial schedule to the service (which is a nested class that implements Runnable) is done in a call like this:

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

I thought that this would make the service run on the EDT but adding System.out.println(SwingUtilities.isEventDispatchThread()); proved that it was not.

I did some searching and found this post that mentioned starting the EDT inside the timer. I tried this and it does work. However, it doesn't seem like a good idea to nest Threads like that.

So, is nesting Threads like this not as bad as it seems? And if it is a bad idea, then what would be the proper way to ensure that a ScheduledExecutorService is running on the EDT?

도움이 되었습니까?

해결책

In your code:

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

The only code executed on the EDT here is the ex.schedule invocation. The code that is then invoked by the scheduler later, eg new UpdatingService() will run on the thread that is internal to the scheduler, which will not be the EDT but some thread created by the call to Executors.newSingleThreadScheduledExecutor

Perhaps what I would do is have your scheduler schedule an update method (your updating service perhaps), which itself then puts a call onto the EDT via invokeLater.

Eg, something like:

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

This is my best advice without seeing what the rest of your code is doing.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top