我有一个关于我一直在努力的事情的一般性问题,并且现在正在寻找答案3天(并且基本上已经放弃了纯粹的挫折感。)
场景1;
A)调用方法,创建并显示“Please wait ..”JWindow组件,其中包含.setVisible(true)
B)调用方法进行简单计算,System.out进行结果
C)“请等待..”在步骤B执行期间按预期持续
D)步骤B终止并且在“请稍候”窗口中调用.setVisible(false)并按预期方式进行
到目前为止,非常好。
情景2;
与方案1相同,不同之处在于步骤B中的工作要复杂得多,并且调用一个自定义类,该类执行大量的db查询/写入,平均需要大约3-6秒才能完成。自定义类不可运行或线程化,只需使用;
调用customClass cc = new customClass();
cc.makeMyDataPlease();
我现在花了2 1/2天的时间试验了这个网站上发现的这些类型问题的许多解决方案,其他人没有运气。尝试过swingworker,invokelater,thread等,并得出结论,我需要在撕掉更多头发之前对此进行更多调查。
我遇到了类似的问题,该方法连接到网址并发布数据。我试图在Web连接例程启动之前在简单的JLabel上设置文本,但它也失败了。文本是在Web例程完成后设置的。
就好像VM正在线程化每个语句执行。
我怀疑mysql类和网络URL类共享属性(网络?),冻结其他可能没有时间完成的任务。
以下是我的问题/疑惑:
如果主java线程中的执行是顺序的,除非创建/调用新线程,为什么会干扰该setVisible(true)语句?它在逻辑上必须在执行数据库例程语句之前完成,但它没有。
java确保一个语句在下一个语句之前完全执行的最终方式是什么? (或者至少,而下一个开始,因为我确信VM可以足够快地执行setVisible,甚至可以同步启动)。
提前致谢
具体来说我的问题是;处理java中“阻止程序”例程所涉及的并发问题以及如何最好地在这些范围内工作时,最佳做法是什么。
答案 0 :(得分:2)
与方案1相同,但步骤B中的工作要复杂得多 并调用一个自定义类,它执行一堆数据库查询/写入 平均需要3-6秒才能完成。自定义类是 不可运行或线程,只需调用;
customClass cc = new customClass(); cc.makeMyDataPlease();对于 无论出于何种原因,在场景2中,.setVisible(true)步骤'A'都可以 直到复杂的工作步骤'B'完成后才会发生。
问题是,Swing是一个单线程环境。期望与UI的所有交互在事件调度线程的上下文中执行。阻止此线程的任何进程都将阻止它处理新事件,包括绘制请求。
正在发生的情况是,场景2最有可能阻止EDT,阻止它显示窗口,而是在所有处理完成时,EDT在打开事件后立即响应关闭事件。 / p>
由于框架的结构方式,您必须确保;
首先查看Concurrency in Swing了解更多详情。
没有进一步的证据,我的直觉是使用SwingWorker
例如......
import java.awt.EventQueue;
import java.util.concurrent.ExecutionException;
import javax.swing.JLabel;
import javax.swing.JWindow;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class QuickWorker {
public static void main(String[] args) {
new QuickWorker();
}
public QuickWorker() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JWindow window = new JWindow();
window.add(new JLabel("Look no hands!"));
window.pack();
window.setLocationRelativeTo(null);
}
});
}
public class Worker extends SwingWorker<Object, Object> {
private JWindow window;
public Worker(JWindow window) {
this.window = window;
}
@Override
protected Object doInBackground() throws Exception {
// Long running process...
Thread.sleep(5000);
return "All done";
}
@Override
protected void done() {
try {
// Get the results of the process if you want them...
get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
window.dispose();
// This is only here because the example will keep running without it :P
System.exit(0);
}
}
}