在我的带有Swing GUI的Java应用程序中,我想实现以下目标。
运行非GUI线程,执行一些工作。有一次,该线程需要用户输入才能继续。然后,我想对GUI进行一些更改,等待特定的GUI操作(如用户按下OK按钮),从GUI输入数据到非GUI线程,并让它继续计算。
环顾四周,我发现了很多关于如何从另一个线程上的Swing GUI线程开始执行(长时间运行)任务的信息,但没有解决我的问题。
SwingUtilites.invokeAndWait
听起来像它的工作,但首先,它需要一个Runnable
参数而不是Callable
,因此没有直接的方法来返回结果,其次,它没有解决等待某个GUI事件的问题。
我意识到我可以使用例如一个CountDownLatch
,但对我来说,问题似乎足够频繁,因为有一个标准的解决方案。
所以,我的问题是:这真的是一个常见的问题,如果是的话,标准库/库中是否有解决方案?如果没有标准解决方案,您会如何解决?如果这个问题不经常发生,为什么不呢?
答案 0 :(得分:6)
启动GUI更改很容易,因此我假设您只是要求将数据恢复到工作线程。
首先,创建一个Blocking Queue。让工作线程在队列上调用take()
,它将阻塞。在GUI空间中,一旦用户输入有效输入,将其放在具有offer()
的队列中,工作线程将接收数据并可以继续。
答案 1 :(得分:1)
我认为,您可以使用 ExecutorService ,也可以通过未来界面跟踪任务进度。
答案 2 :(得分:1)
java.awt.EventQueue.invokeLater
非常适合在AWT EDT上运行代码。可能最好复制可变数据或更好地使用不可变数据。锁是可能的,但有点冒险。
如果你的其他线程是一个事件调度循环,你可以为你的线程实现invokeLater
之类的东西(但不要让它变为静态!)。可能在一些对线程行为有意义的接口后面使用它 - 所以它是真正的操作而不是run
被指定为做任何它喜欢的事情。如果您的线程要阻止,那么BlockQueue
就可以了,但不要阻止AWT EDT。
java.awt.EventQueue.invokeAndWait
就像使用锁一样。可能你会使用另一把锁。或者也许是你自己的线程上的invokeAndWait
之类的锁。如果你不这样做,AWT无论如何都会使用锁。所以,不受控制的嵌套锁,这可能意味着死锁。不要使用invokeAndWait
!
答案 3 :(得分:0)
final bool result = doSomething();
SwingUtilities.invokeLater( new Runnable(){
//Runnable method implementation.
//use result in your method like local var.
});
确保使用锁定对象同步共享数据。 如果需要将参数传递给Runnable,只需将局部变量设为final, 并在run方法中使用它们。