JOptionPane.showMessageDialog线程安全吗?

JOptionPane.showMessageDialog应该是一个有用的实用程序,用于获取用户反馈,因为它会在您等待时阻止当前线程。

因此我希望它是线程安全的,你不需要在invokeLater或invokeAndWait中包装调用。

是这样的吗?

取自javax.swing包描述:

Swing的线程策略

一般来说,Swing不是线程安全的。 除非另有说明,否则必须在事件派发线程上访问所有Swing组件和相关类。 典型的Swing应用程序响应于从用户手势生成的事件进行处理。 例如,单击JButton会通知添加到JButton的所有ActionListener。 由于在事件调度线程上调度了从用户手势生成的所有事件,因此大多数开发人员不受限制的影响。

然而,影响在于构建和显示Swing应用程序。 不会在事件派发线程上调用对应用程序的主方法或Applet中的方法的调用。 因此,在构造和显示应用程序或applet时,必须注意将控制转移到事件调度线程。 传递控制并开始使用Swing的首选方法是使用invokeLater。 invokeLater方法调度要在事件分派线程上处理的Runnable。

JOptionPane没有记录它是线程安全的,所以你必须使用invokeLater()

您应该只从事件调度线程调用此方法,因为这是应该与Swing组件交互的唯一线程。

如果您希望在等待用户反馈的同时暂停后台处理,我建议您使用SwingWorker实现,其中doInBackground()方法定期调用publish() ,允许在Swing线程上调用process() 。 然后, doInBackground()可能会阻塞,直到在process()某些操作。 例如:

 new SwingWorker() { 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 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(); 

不,情况并非如此。 阻塞行为非常具体地编码到事件队列中(通过推送新队列以便可以处理更多事件并阻止此事件)。 与所有swing组件一样,它们只能在事件队列中使用。