Безопасна ли JOptionPane.showMessageDialog?

127
10

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


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


В этом случае?

спросил(а) 2009-10-20T19:10:00+04:00 11 лет назад
1
Решение
121

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


Политика качания потоков

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

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


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

ответил(а) 2009-10-20T19:21:00+04:00 11 лет назад
114

Вы должны вызывать этот метод только из потока отправки событий, так как это единственный поток, который должен взаимодействовать с компонентами 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();

ответил(а) 2009-10-20T19:17:00+04:00 11 лет назад
99

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

ответил(а) 2009-10-20T19:22:00+04:00 11 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема