[英]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的创建/修改/交互。
更新
基本工作流程(IMHO)应该类似于...
loadingDone
从后台线程请求数据,将侦听器接口传递到后台线程(使用loadingDone
和loadingFailed
这样的方法进行loadingDone
loadingDone
方法传回 loadingDone
调用loadingDone
,与EDT重新同步(使用SwingUtilities.invokeLater
)并更新UI。 使用SwingWorker
实际上会更简单,并且它将提供内置的进度更新
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.