java - 如何使用wait()和notifyAll()在GUI类和逻辑线程之间进行通信

标签 java multithreading swing event-dispatch-thread

我的类(class)中有 3 个主要类(class)。第一个扩展小程序(并充当我的主程序),第二个是处理后端物流/与服务器通信的线程(实现 Runnable),第三个是 JPanel 类,它创建 GUI(这是创建的)在新线程中通过调用主(小程序)类中的 SwingUtilities.invokeAndWait() 来实现。

GUI 类与后端线程多次通信以获取要在屏幕上显示的数据。我的问题是,GUI 在后端类向其组件提供数据之前就显示了它们。因此,我想告诉 GUI 调用另一个线程中的方法,等待收到它的回复,然后显示其组件。我尝试过以下几种变体:

Object[] data = backend.Method1(); 
wait();
showComponents(data);

在 GUI 类上,并将 notifyAll(); 放置在后端线程中 Method1 的底部,但我在 netbeans 中收到警告(在同步上下文之外调用 Object.wait ),并且程序在运行时会因 java.lang.illegalmonitorstateException 崩溃。我尝试将 synchronized 关键字添加到这两个方法中,但这会导致程序卡住。

我(显然,我确信)刚刚学习多线程:我在这里误解了什么?

我有一种感觉,这与 JPanel 类没有实现 runnable 相关。

编辑:根据@MadProgrammer的建议,我正在使用SwingWorker,它似乎可以解决问题。感谢您向我指出,我以前从未听说过它们。

 final JLabel loading = new JLabel("loading");
    loading.setVisible(true);
    add(loading);

    SwingWorker sw = new SwingWorker<Map<String, ArrayList<Time[]>>, Void>() {
        @Override
        public Map<String, ArrayList<Time[]>> doInBackground(){
            System.out.println("doing");
            Map<String, ArrayList<Time[]>> toReturn = dbh.getTimes(specToPass);
            return toReturn;
        }

        public void done(){
            try {
                loading.setVisible(false);
                Map<String, ArrayList<Time[]>> weekMap = new HashMap(this.get());
                showTimes(weekMap);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            } catch (ExecutionException ex) {
                  ex.printStackTrace();
            }
       }
    };
    sw.execute();

如果我没有正确执行此操作,希望您能告诉我。再次感谢。

最佳答案

不要。以任何方式阻止用户界面总是一个坏主意。这将使您的应用程序“挂起”并阻止 UI 更新(或响应用户的任何输入)。

这会带来非常糟糕的用户体验。

相反,使用某种回调,允许数据线程根据需要将更新发送回 UI。这应该允许您的 UI 在等待来自数据线程的数据时显示类似“等待”消息的内容。

您还可以使用 SwingWorker 来处理数据收集,但它可能对您的所有需求来说都很简单,但它提供了将任何更新同步回 UI 的简单方法。

确保所有与 UI 的创建/修改/交互都是在事件调度线程的上下文中完成的。

看看Concurrency in Swing了解更多详情

已更新

基本工作流程(恕我直言)应该看起来像......

  • UI - 从后台线程请求数据,传递监听器接口(interface) 到后台线程(使用诸如 loadingDone 和 例如 loadingFailed
  • UI - 显示“正在加载”消息。可以显示漂亮的动画 GIF
  • Thread - 加载数据时(假设一切顺利),打包数据并通过 loadingDone 方法将其传回
  • UI - 调用 loadingDone 时,与 EDT 重新同步(使用 SwingUtilities.invokeLater)并更新 UI。

使用 SwingWorker 实际上会更简单,并且它将提供内置的进度更新

关于java - 如何使用wait()和notifyAll()在GUI类和逻辑线程之间进行通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15492303/

相关文章:

Java 游戏(箭头控制)速度减慢,鼠标在 JFrame 外部移动期间除外

Java Swing 仅将文件中的唯一行读取到 JtextArea 中

java - 如何停止和重新启动线程内的循环?

java - 从 SQLite 数据库中选择特定行-ANDROID-SQLite 数据库

java - Java中的final关键字是类型限定符吗?

java - 如何管理CPU资源

java - 我如何从 Java 中的另一个线程杀死一个线程?

java - 错误帮助,数组在高值时越界

java - 如何从 org.springframework.data.repository.CrudRepository 后代取消代理子对象

c++ - 有没有办法标记不可重入 C 库调用的使用?