繁体   English   中英

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

[英]How to use wait() and notifyAll() to communicate between a GUI class and logic thread

我的程序中有3个初级班。 第一个扩展小程序(并充当我的主程序),第二个扩展是处理后端物流/与服务器通信的线程(实现Runnable),第三个扩展是创建GUI的JPanel类(创建通过调用主(小应用程序)类中的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。 这应该使您的UI在等待数据线程中的数据时显示“等待”消息。

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

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

查看Swing中的并发以了解更多详细信息

更新

基本工作流程(IMHO)应该类似于...

  • loadingDone从后台线程请求数据,将侦听器接口传递到后台线程(使用loadingDoneloadingFailed这样的方法进行loadingDone
  • UI-显示“正在加载”消息。 可能会显示精美的GIF动画
  • 线程-加载数据时(假设一切顺利),打包数据并通过loadingDone方法传回
  • loadingDone调用loadingDone ,与EDT重新同步(使用SwingUtilities.invokeLater )并更新UI。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM