SwingUtilites:如何从Java中的另一个线程返回值?

Ash*_*egi 6 java swing multithreading input swingutilities

我正在尝试用Java创建一个应用程序.为了使Swing正常工作,我这样做了:

public static void main(String[] array){ 

String outerInput;
SwingUtilities.invokeLater(new Runnable(){
    @Override
    public void run() {
        // I want this string input.
        String input = JOptionPane.showInputDialog(
            null,"Stop ?", JOptionPane.QUESTION_MESSAGE);  
});
// How can I get this input value in String outerInput?
}
Run Code Online (Sandbox Code Playgroud)

我如何在我的主体中获得此输入字符串?

par*_*fal 6

我如何在我的主体中获得此输入字符串?

你不会.您的"main"将调用Swing对话框然后对结果执行某些操作的想法与图形用户界面的整个想法相反.

在GUI中,您可以设计程序来处理一系列用户启动的事件.这些事件可能是完全异步的,例如典型文字处理器的击键,选择和菜单选择.或者它们可能是脚本化的,例如"向导"的问答形式.

假设您想要执行后者之类的操作,您可以使用以下顺序实现它:

  1. 用户启动一些操作,可能选择菜单选项.这转化为a的调用ActionListener,决定它需要来自用户的更多输入.
  2. ActionListener该事件调度线程上执行,被允许做任何它想要的UI,比如显示一个对话框.该对话可以是模态的或非模态的; 在一种情况下,输出可用于原始侦听器,而另一种情况则需要编写新的侦听器以执行后续操作.
  3. 获得足够的信息后,您可以选择调用后台操作.您通常会有一个线程池来为这些请求提供服务.您不会尝试在"主"线程上执行请求; 事实上,对于所有意图,主线程不再运行.
  4. 当您的操作完成运行时,它会使用数据将数据推送回事件派发线程SwingUtilities.invokeLater().虽然您可以使用invokeAndWait()在后台操作过程中将结果发送到Swing,但这不是一个好主意.而是创建一系列操作,最好是一个易于被用户取消的操作.

在后台线程上启动操作的"标准"方法是通过SwingWorker.还有其他选择; 例如,您可以使用a BlockingQueue将操作发送到单个长时间运行的后台线程,并用于invokeLater()返回结果.

无论如何,有你一个规则希望打破:永远,永远,事件调度线程上执行阻塞操作.如果您这样做,那么您的应用程序就会被破坏.


Pet*_*aný 5

您可以使用AtomicReference<String>以线程安全的方式在线程之间传递值.

正如Hemal所说,你需要在两个线程之间进行一些同步,以确保它已经被执行.例如,您可以使用CountDownLatch或使用SwingUtilities.invokeAndWait(确保您不要从Swing线程调用它!)

更新:这是使用AtomicReferenceCountDownLatch的完整示例

public class Main {
    public static void main(String[] args) throws InterruptedException {
        final AtomicReference<String> result = new AtomicReference<String>();
        final CountDownLatch latch = new CountDownLatch(1);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                String input = JOptionPane.showInputDialog(null, "Stop?", "Stop?", JOptionPane.QUESTION_MESSAGE);
                result.set(input);

                // Signal main thread that we're done and result is set.
                // Note that this doesn't block. We never call blocking methods
                // from Swing Thread!
                latch.countDown();
            }
        });

        // Here we need to wait until result is set. For demonstration purposes,
        // we use latch in this code. Using SwingUtilities.invokeAndWait() would
        // be slightly better in this case.

        latch.await();

        System.out.println(result.get());
    }
}
Run Code Online (Sandbox Code Playgroud)

另请阅读有关GUI(和Swing)应用程序的一般设计的答案.