JOptionPane.showMessageDialog поток безопасно?
Предполагается, что JOptionPane.showMessageDialog будет полезной утилитой для получения отзывов пользователей, поскольку она блокирует ваш текущий поток, пока вы ждете.
Поэтому я ожидал бы, что это будет поточно-ориентированным и что вам не нужно будет оборачивать вызов в invokeLater или invokeAndWait.
Это тот случай?
3 ответа
Взято из описания пакета javax.swing:
Политика потоков Swing
В общем, Swing не является потокобезопасным. Все компоненты Swing и связанные с ними классы, если не указано иное, должны быть доступны в потоке диспетчеризации событий. Типичные приложения Swing выполняют обработку в ответ на событие, сгенерированное жестом пользователя. Например, нажатие на JButton уведомляет все ActionListeners, добавленные в JButton. Поскольку все события, сгенерированные из жеста пользователя, отправляются в потоке диспетчеризации событий, это ограничение не влияет на большинство разработчиков.
Однако влияние заключается в создании и демонстрации приложения Swing. Вызовы основного метода приложения или методов в Applet не вызываются в потоке диспетчеризации событий. В связи с этим необходимо позаботиться о передаче управления потоку диспетчеризации событий при создании и отображении приложения или апплета. Предпочтительным способом передачи управления и начала работы с Swing является использование invokeLater. Метод invokeLater планирует Runnable для обработки в потоке диспетчеризации событий.
JOptionPane не документирует, что это потокобезопасный, поэтому вы должны использовать invokeLater()
,
Вы должны вызывать этот метод только из потока диспетчеризации событий, так как это единственный поток, который должен взаимодействовать с компонентами 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();
Нет, это не так. Поведение блокировки очень точно закодировано в очереди событий (путем добавления новой очереди, чтобы можно было обработать дальнейшие события, и блокировки этой). Как и для всех компонентов колебания, они могут использоваться только в очереди событий.