Java Swing应用程序:如何从GUI线程获取数据到另一个线程?

时间:2012-02-22 15:14:32

标签: java multithreading swing concurrency

在我的带有Swing GUI的Java应用程序中,我想实现以下目标。

运行非GUI线程,执行一些工作。有一次,该线程需要用户输入才能继续。然后,我想对GUI进行一些更改,等待特定的GUI操作(如用户按下OK按钮),从GUI输入数据到非GUI线程,并让它继续计算。

环顾四周,我发现了很多关于如何从另一个线程上的Swing GUI线程开始执行(长时间运行)任务的信息,但没有解决我的问题。

SwingUtilites.invokeAndWait听起来像它的工作,但首先,它需要一个Runnable参数而不是Callable,因此没有直接的方法来返回结果,其次,它没有解决等待某个GUI事件的问题。

我意识到我可以使用例如一个CountDownLatch,但对我来说,问题似乎足够频繁,因为有一个标准的解决方案。

所以,我的问题是:这真的是一个常见的问题,如果是的话,标准库/库中是否有解决方案?如果没有标准解决方案,您会如何解决?如果这个问题不经常发生,为什么不呢?

4 个答案:

答案 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方法中使用它们。