JOptionPane.showMessageDialog应该是一个有用的实用程序,用于获取用户反馈,因为它会在您等待时阻止当前线程。
因此我希望它是线程安全的,你不需要在invokeLater或invokeAndWait中包装调用。
是这样的吗?
答案 0 :(得分:8)
取自javax.swing包描述:
Swing的线程策略
一般来说,Swing不是线程安全的。除非另有说明,否则必须在事件派发线程上访问所有Swing组件和相关类。典型的Swing应用程序响应于从用户手势生成的事件进行处理。例如,单击JButton会通知添加到JButton的所有ActionListener。由于在事件调度线程上调度了从用户手势生成的所有事件,因此大多数开发人员不受限制的影响。
然而,影响在于构建和显示Swing应用程序。不会在事件派发线程上调用对应用程序的主方法或Applet中的方法的调用。因此,在构造和显示应用程序或applet时,必须注意将控制转移到事件调度线程。传递控制并开始使用Swing的首选方法是使用invokeLater。 invokeLater方法调度要在事件派发线程上处理的Runnable。
JOptionPane没有记录它是线程安全的,所以你必须使用invokeLater()
。
答案 1 :(得分:7)
您应该只从事件派发线程调用此方法,因为这是应该与Swing组件交互的唯一线程。
如果您希望在等待用户反馈的同时暂停后台处理,建议您使用SwingWorker实施,doInBackground()
方法定期调用publish()
,允许调用process()
在Swing线程上。然后,doInBackground()
可能会阻止,直到process()
内采取某些操作为止。例如:
new SwingWorker<Void, Void>() {
private volatile boolean done;
// Called on background thread
public void doInBackground() {
for (int i=0; i<1000000; ++i) {
// Do work
if (i % 1000 == 0) {
publish(); // Will cause process() to be called on Event Dispatch thread.
synchronized(this) {
wait();
}
if (done) {
System.err.println("Background thread stopping.");
return null;
}
}
}
}
// Called on Event dispatch thread.
protected void process(List<Void> chunks) {
if (JOptionPane.showConfirmDialog(getFrame(),
"Do you want to quit?", "Confirm Quit",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
done = true;
}
synchronized(this) {
notifyAll();
}
}
}.execute();
答案 2 :(得分:5)
不,事实并非如此。阻塞行为非常具体地编码到事件队列中(通过推送新队列以便可以处理更多事件并阻止此事件)。与所有swing组件一样,它们只能在事件队列中使用。