JOptionPane.showMessageDialog线程安全吗?

时间:2009-10-20 16:10:07

标签: java swing thread-safety

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

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

是这样的吗?

3 个答案:

答案 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组件一样,它们只能在事件队列中使用。