我已经引用this previous question以及其他来源,但是无法使CountDownLatch正常工作。
背景:mainFrame创建一个名为dataEntryFrame的新框架。单击dataEntryFrame的“提交”按钮时,记录将添加到数据库中,并且dataEntryFrame将被处置。此时,mainFrame应该清除并重新加载显示所有记录的jList。
问题:当dataEntryFrame加载时,java冻结,dataEntryFrame组件从不加载。
我无法超越这部分...
然后,在DataEntryFrame中,CountDownLatch仅应在单击“提交”按钮后递减,然后将记录成功添加到数据库表中并自行处理。或者当用户单击“取消”时...
代码:来自大型机
clearList();
CountDownLatch dataEntryDone = new CountDownLatch(1);
DataEntryFrame f = new DataEntryFrame(dataEntryDone);
Thread newThread = new Thread(f);
newThread.start();
dataEntryDone.await();
reLoadList();
代码:从DataEntryFrame
public void run(){
initComponents();
loadOtherData();
this.setVisible(true);
}
void submit(){
addRecord();
this.dispose()
dataEntryDone.countDown();
}
最佳答案
为dataEntryFrame使用新线程并阻塞mainFrame违反了Swing线程模型。在Swing中,对Swing中的UI组件的所有调用都必须在事件调度线程上进行。为了验证在开发过程中是否发生了这种情况,可以安装一个重新绘制管理器,如果它检测到另一个线程正在使用UI组件,则抛出异常。请参见FEST-Testing that access to GUI components is done in the EDT。为确保在EDT上发生某些事情,请使用SwingUtilities.invokeAndWait / invokeLater。
您的主框架不必(也不应该!)不必等待数据输入框架,而不必等待CountDownLatch,而是让数据输入框架在完成后向MainFrame触发一个事件,以便MainFrame可以采取适当的措施。操作,例如刷新列表。
只是为了进一步解决问题,理想情况下,不应该在事件分发线程上完成将数据保存到数据库并为列表获取数据的工作。而是使用SwingWorker在其自己的线程中执行这些操作。但是,与必须从EDT中访问所有UI组件的规则不同,此后台处理规则并非一成不变,但建议保持响应式UI-如果与db之间的数据传输需要任何时间,并且在UI线程(EDT)上完成操作,然后UI将冻结。
看到
Worker Threads and SwingWorker上的Sun Totorial
the Last Word in Swing Threads