public static void moveTo(Coordinate destination) {
changeState(State.NAVIGATION);
controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));
dmc.moveTo(destination);
changeState(State.IMMEDIATE);
controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}
在此代码中,addRemote方法使用新按钮更新controlPnl GUI。 dmc.moveTo方法中最多有两个Thread.sleep调用,我认为它们是在更新controlPnl GUI之前调用的。我已经注释掉dmc.moveTo之后的两个方法调用,它将GUI更改回调用之前的状态,并且controlPnl在moveTo完成执行之前不会完成更新。我需要的是GUI在moveTo方法开始执行之前完成更新并将Thread置于休眠状态。有什么办法可以在Java 6中实现这个目标吗?
如果重要,moveTo方法会将LEGO Mindstorm机器人移动到用户定义的路径上的指定点。正在更新的GUI为用户提供Swing组件(JButtons和JRadioButtons),以便在导航时控制机器人。 addRemote方法更改用户要使用的Swing组件集,moveTo方法向机器人发送命令以实际执行移动(通过告诉其电机移动,睡眠正确的时间,然后告诉其电机停止移动)。我正在使用状态机模式,此方法是处理来自UI的事件的控制器的一部分。
答案 0 :(得分:0)
您有一个GUI线程。不要用它来打电话给其他东西;如果你这样做,那些事情必须在你的GUI中发生任何其他事情之前完成。
至少你会想要开始一个新线程来执行你的dmc.moveTo(destination)
。很可能这不是您正在执行此操作的唯一地方,并且可能需要Executor设置来执行这些任务。
在不了解您的代码的情况下(特别是因为您使用的是静态方法)我无法评论您希望如何设置Executor
,而是使用Thread
的最简单示例将是:
public static void moveTo(final Coordinate destination) {
changeState(State.NAVIGATION);
controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));
new Thread(new Runnable() {
public void run() {
dmc.moveTo(destination);
changeState(State.IMMEDIATE);
controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}
}).start();
}
这会创建一个新的Thread
,用于执行执行Runnable
的(匿名)moveTo()
。请注意,这比准备好运行任务的Executor
效率低得多;它必须每次创建一个新的Thread
。但是,如果这不是你需要的性能问题那么它就完全没问题了。另请注意,因为我在匿名内部类中直接引用destination
,所以在传递给您的方法时必须将其声明为final
。
答案 1 :(得分:0)
由于moveTo
需要很长时间,因此不应在主事件处理线程上执行它。相反,让moveTo
更新GUI并在单独的线程中开始实际移动。移动完成后,使用SwingUtilities.invokeLater
进行第二组GUI更新。
private static ExecutorService executor = Executors.newCachedThreadPool();
public static void moveTo(final Coordinate destination) {
changeState(State.NAVIGATION);
controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));
executor.execute(new Runnable() {
public void run() {
dmc.moveTo(destination);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
changeState(State.IMMEDIATE);
controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}
});
}
});
}
这种方式moveTo
执行初始的GUI更新集,然后立即返回,释放事件循环以保持GUI响应,但第二个changeState
被延迟,直到dmc.moveTo
为止完整。
(将这些东西分解为单独的方法而不是使用Runnable-in-a-Runnable匿名类可能更有意义)