JOptionPane.showMessageDialog线程安全吗?

Tom*_*tin 9 java swing thread-safety

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

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

是这样的吗?

tan*_*ens 8

取自javax.swing包描述:

Swing的线程策略

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

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

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


Ada*_*ski 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();
Run Code Online (Sandbox Code Playgroud)


Yis*_*hai 5

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