Является ли JOptionPane.showMessageDialog потокобезопасным?

Предполагается, что JOptionPane.showMessageDialog является полезной утилитой для получения отзывов пользователей, поскольку она блокирует ваш текущий поток, пока вы ждете.

Поэтому я ожидаю, что он будет потокобезопасным и что вам не нужно будет оборачивать вызов в invokeLater или invokeAndWait.

Так ли это?


person Tom Martin    schedule 20.10.2009    source источник
comment
В ответах и ​​комментариях на этот вопрос есть соответствующее обсуждение. Один из аргументов заключается в том, что хотя он и не является потокобезопасным, на практике это не проблема, и нет необходимости запускать его в EDT.   -  person THelper    schedule 11.09.2014


Ответы (3)


Взято из описания пакета javax.swing:

Политика потоков Swing

В целом Swing не является потокобезопасным. Все компоненты Swing и связанные с ними классы, если не указано иное, должны быть доступны в потоке диспетчеризации событий. Типичные приложения Swing выполняют обработку в ответ на событие, сгенерированное жестом пользователя. Например, щелчок по кнопке JButton уведомляет все прослушиватели действий, добавленные к кнопке JButton. Поскольку все события, сгенерированные жестом пользователя, отправляются в поток диспетчеризации событий, это ограничение не затрагивает большинство разработчиков.

Однако влияние заключается в создании и отображении приложения Swing. Вызовы основного метода приложения или методов апплета не вызываются в потоке диспетчеризации событий. Таким образом, необходимо позаботиться о передаче управления потоку диспетчеризации событий при создании и отображении приложения или апплета. Предпочтительный способ передать управление и начать работу с Swing — использовать invokeLater. Метод invokeLater планирует обработку Runnable в потоке диспетчеризации событий.

JOptionPane не документирует, что он является потокобезопасным, поэтому вы должны использовать invokeLater().

person tangens    schedule 20.10.2009
comment
JOptionPane никогда не используется вне потока очереди событий. Если вы попытаетесь изменить или что-то еще, это будет небезопасно для потока. - person bestsss; 21.01.2011

Вы должны вызывать этот метод только из потока диспетчеризации событий, так как это единственный поток, который должен взаимодействовать с компонентами 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();
person Adamski    schedule 20.10.2009
comment
Спасибо, я знаком с SwingWorker. - person Tom Martin; 20.10.2009
comment
Нет проблем ... хотя спорно, хотите ли вы на самом деле приостановить свой фоновый поток во время отображения диалогового окна; вероятно, имеет смысл продолжать обработку до тех пор, пока пользователь не примет решение. - person Adamski; 20.10.2009

Нет, это не так. Поведение блокировки очень конкретно закодировано в очереди событий (путем добавления новой очереди для обработки дальнейших событий и блокировки этой очереди). Как и все компоненты Swing, их можно использовать только в очереди событий.

person Yishai    schedule 20.10.2009