Класс SwingWorker<T, V>
- Параметры типа:
T- тип результата, возвращаемого методамиSwingWorker'sdoInBackgroundиgetэтого классаV- тип, используемый для передачи промежуточных результатов методамиSwingWorker'spublishиprocessэтого класса
- Все реализуемые интерфейсы:
Runnable, Future<T>, RunnableFuture<T>
public abstract class SwingWorker<T,V> extends Object implements RunnableFuture<T>
SwingWorker не определена, и полагаться на неё не следует. При написании многопоточного приложения с использованием Swing следует учитывать два ограничения (подробнее см. в разделе Параллельная обработка в Swing ):
- Длительные задачи не следует выполнять в потоке обработки событий. В противном случае приложение перестанет отвечать на запросы.
- Доступ к компонентам Swing должен осуществляться только в потоке обработки событий.
Эти ограничения означают, что приложению с графическим интерфейсом, выполняющему длительные вычисления, требуется как минимум два потока: 1) поток для выполнения длительной задачи и 2) поток обработки событий (EDT) для всех действий, связанных с графическим интерфейсом. Для этого требуется межпоточное взаимодействие, реализация которого может быть непростой.
SwingWorker предназначен для ситуаций, когда длительную задачу требуется выполнять в фоновом потоке и сообщать об изменениях пользовательскому интерфейсу после её завершения или во время её выполнения. Подклассы SwingWorker должны реализовать метод doInBackground() для выполнения фоновых вычислений.
Рабочий процесс
В жизненном цикле SwingWorker участвуют три потока:
-
Текущий поток: метод
execute()вызывается в этом потоке. Он планирует выполнениеSwingWorkerв рабочем потоке и немедленно возвращает управление. Дождаться завершенияSwingWorkerможно с помощью методовget. -
Рабочий поток: метод
doInBackground()вызывается в этом потоке. Здесь должны выполняться все фоновые действия. Чтобы уведомитьPropertyChangeListenersоб изменениях связанных свойств, используйте методыfirePropertyChangeиgetPropertyChangeSupport(). По умолчанию доступны два связанных свойства:stateиprogress. -
Поток обработки событий: все действия, связанные со Swing, выполняются в этом потоке.
SwingWorkerвызывает методыprocessиdone(), а также уведомляет всеPropertyChangeListenersв этом потоке.
Часто текущим потоком является поток обработки событий.
Перед вызовом метода doInBackground в рабочем потоке SwingWorker уведомляет все PropertyChangeListeners об изменении свойства state на StateValue.STARTED. После завершения метода doInBackground выполняется метод done. Затем SwingWorker уведомляет все PropertyChangeListeners об изменении свойства state на StateValue.DONE.
SwingWorker предназначен для однократного выполнения. Повторное выполнение SwingWorker не приведёт к повторному вызову метода doInBackground.
Пример использования
В следующем примере показан простейший вариант использования. Некоторая обработка выполняется в фоновом режиме, а после её завершения обновляется компонент Swing.
Допустим, мы хотим найти «смысл жизни» и отобразить результат в JLabel.
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
return findTheMeaningOfLife();
}
@Override
protected void done() {
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
(new MeaningOfLifeFinder()).execute();
Следующий пример полезен в ситуациях, когда данные нужно обрабатывать по мере их готовности в потоке обработки событий.
Теперь мы хотим найти первые N простых чисел и отобразить результаты в JTextArea. Пока выполняются вычисления, мы хотим обновлять ход выполнения в JProgressBar. Наконец, мы также хотим вывести простые числа в System.out.
class PrimeNumbersTask extends
SwingWorker<List<Integer>, Integer> {
PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
//initialize
}
@Override
public List<Integer> doInBackground() {
while (! enough && ! isCancelled()) {
number = nextPrimeNumber();
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
}
return numbers;
}
@Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
}
JTextArea textArea = new JTextArea();
final JProgressBar progressBar = new JProgressBar(0, 100);
PrimeNumbersTask task = new PrimeNumbersTask(textArea, N);
task.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer)evt.getNewValue());
}
}
});
task.execute();
System.out.println(task.get()); //prints all prime numbers we have got
Поскольку SwingWorker реализует Runnable, SwingWorker можно передать на выполнение объекту Executor.
- С момента выпуска:
- 1.6
Краткое описание вложенных классов
| Модификатор и тип | Класс | Описание |
|---|---|---|
static enum |
SwingWorker.StateValue |
Значения связанного свойства state. |
Вложенные классы и интерфейсы, объявленные в интерфейсе Future
Future.State
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
SwingWorker() |
Создаёт этот SwingWorker. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
final void |
addPropertyChangeListener |
Добавляет PropertyChangeListener в список слушателей. |
final boolean |
cancel |
Пытается отменить выполнение этой задачи. |
protected abstract T |
doInBackground() |
Вычисляет результат или выбрасывает исключение, если это невозможно. |
protected void |
done() |
Выполняется в потоке обработки событий после завершения метода doInBackground. |
final void |
execute() |
Планирует выполнение этого SwingWorker в рабочем потоке. |
final void |
firePropertyChange |
Сообщает зарегистрированным слушателям об обновлении связанного свойства. |
final T |
get() |
При необходимости ожидает завершения вычисления, а затем возвращает его результат. |
final T |
get |
При необходимости ожидает завершения вычисления не дольше указанного времени, а затем возвращает его результат, если он доступен. |
final int |
getProgress() |
Возвращает связанное свойство progress. |
final PropertyChangeSupport |
getPropertyChangeSupport() |
Возвращает PropertyChangeSupport для этого SwingWorker. |
final SwingWorker.StateValue |
getState() |
Возвращает связанное свойство состояния SwingWorker. |
final boolean |
isCancelled() |
Возвращает true, если эта задача была отменена до её нормального завершения. |
final boolean |
isDone() |
Возвращает true, если эта задача завершилась. |
protected void |
process |
Асинхронно получает фрагменты данных из метода publish в потоке обработки событий. |
protected final void |
publish |
Передаёт фрагменты данных методу process(List). |
final void |
removePropertyChangeListener |
Удаляет PropertyChangeListener из списка слушателей. |
final void |
run() |
Устанавливает для этого Future результат вычисления, если задача не была отменена. |
protected final void |
setProgress |
Устанавливает связанное свойство progress. |
Методы, объявленные в классе Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Методы, объявленные в интерфейсе Future
exceptionNow, resultNow, state
Подробное описание конструкторов
SwingWorker
public SwingWorker()
SwingWorker.Подробное описание методов
doInBackground
protected abstract T doInBackground() throws Exception
Обратите внимание, что этот метод выполняется только один раз.
Примечание: этот метод выполняется в фоновом потоке.
- Возвращает:
- вычисленный результат
- Выбрасывает:
-
Exception- если вычислить результат невозможно
run
public final void run()
Future результат вычисления, если задача не была отменена.- Определён в:
-
runв интерфейсеRunnable - Определён в:
-
runв интерфейсеRunnableFuture<T>
publish
@SafeVarargs protected final void publish(V... chunks)
process(List). Этот метод следует вызывать из метода doInBackground, чтобы передать промежуточные результаты для обработки в потоке обработки событий внутри метода process. Поскольку метод process вызывается асинхронно в потоке обработки событий, до выполнения метода process может произойти несколько вызовов метода publish. Для повышения производительности все эти вызовы объединяются в один вызов с объединёнными аргументами.
Например:
publish("1");
publish("2", "3");
publish("4", "5", "6");
может привести к:
process("1", "2", "3", "4", "5", "6")
Пример использования. Этот фрагмент кода загружает табличные данные и обновляет ими DefaultTableModel. Обратите внимание: изменять tableModel внутри метода process безопасно, поскольку он вызывается в потоке обработки событий.
class TableSwingWorker extends
SwingWorker<DefaultTableModel, Object[]> {
private final DefaultTableModel tableModel;
public TableSwingWorker(DefaultTableModel tableModel) {
this.tableModel = tableModel;
}
@Override
protected DefaultTableModel doInBackground() throws Exception {
for (Object[] row = loadData();
! isCancelled() && row != null;
row = loadData()) {
publish((Object[]) row);
}
return tableModel;
}
@Override
protected void process(List<Object[]> chunks) {
for (Object[] row : chunks) {
tableModel.addRow(row);
}
}
}
- Параметры:
-
chunks- промежуточные результаты для обработки - См. также:
process
protected void process(List<V> chunks)
publish в потоке обработки событий. Дополнительные сведения см. в описании метода publish(V...).
- Параметры:
-
chunks- промежуточные результаты для обработки - См. также:
done
protected void done()
doInBackground. Реализация по умолчанию ничего не делает. Подклассы могут переопределить этот метод, чтобы выполнять завершающие действия в потоке обработки событий. Обратите внимание: внутри реализации этого метода можно проверить состояние, чтобы определить результат задачи или узнать, была ли она отменена.- См. также:
setProgress
protected final void setProgress(int progress)
progress. Значение должно находиться в диапазоне от 0 до 100. Поскольку уведомления PropertyChangeListeners отправляются асинхронно в потоке обработки событий, до вызова любых PropertyChangeListeners может произойти несколько вызовов метода setProgress. Для повышения производительности все эти вызовы объединяются в один, содержащий только аргумент последнего вызова.
Например, следующие вызовы:
setProgress(1); setProgress(2); setProgress(3);могут привести к одному уведомлению
PropertyChangeListener со значением 3.- Параметры:
-
progress- устанавливаемое значение прогресса - Выбрасывает:
-
IllegalArgumentException- если значение не находится в диапазоне от 0 до 100
getProgress
public final int getProgress()
progress.- Возвращает:
- связанное свойство прогресса.
execute
public final void execute()
SwingWorker в рабочем потоке. Доступно несколько рабочих потоков. Если все рабочие потоки заняты выполнением других SwingWorkers, этот SwingWorker помещается в очередь ожидания. Примечание: SwingWorker предназначен для однократного выполнения. Повторное выполнение SwingWorker не приведёт к повторному вызову метода doInBackground.
cancel
public final boolean cancel(boolean mayInterruptIfRunning)
cancel, она не должна запускаться. Если задача уже запущена, параметр mayInterruptIfRunning определяет, следует ли прервать поток, выполняющий эту задачу (если реализация может его определить), чтобы попытаться остановить задачу. Возвращаемое этим методом значение не обязательно указывает, отменена ли задача; используйте Future.isCancelled().
- Определён в:
-
cancelв интерфейсеFuture<T> - Параметры:
-
mayInterruptIfRunning-true, если поток, выполняющий эту задачу, следует прервать (если реализация может его определить); в противном случае выполняющимся задачам разрешается завершиться - Возвращает:
-
false, если задачу не удалось отменить, обычно потому, что она уже завершена; в противном случае —true. Если два или более потока пытаются отменить задачу, по крайней мере один из них возвращаетtrue. Реализации могут предоставлять более строгие гарантии.
isCancelled
public final boolean isCancelled()
true, если эта задача была отменена до её нормального завершения.- Определён в:
-
isCancelledв интерфейсеFuture<T> - Возвращает:
-
true, если эта задача была отменена до завершения
isDone
get
public final T get() throws InterruptedException, ExecutionException
Примечание: вызов get в потоке обработки событий блокирует обработку всех событий, включая перерисовку, до завершения этого SwingWorker.
Если требуется заблокировать поток обработки событий до завершения SwingWorker, рекомендуется использовать модальное диалоговое окно.
Например:
class SwingWorkerCompletionWaiter implements PropertyChangeListener {
private JDialog dialog;
public SwingWorkerCompletionWaiter(JDialog dialog) {
this.dialog = dialog;
}
public void propertyChange(PropertyChangeEvent event) {
if ("state".equals(event.getPropertyName())
&& SwingWorker.StateValue.DONE == event.getNewValue()) {
dialog.setVisible(false);
dialog.dispose();
}
}
}
JDialog dialog = new JDialog(owner, true);
swingWorker.addPropertyChangeListener(
new SwingWorkerCompletionWaiter(dialog));
swingWorker.execute();
//the dialog will be visible until the SwingWorker is done
dialog.setVisible(true);
- Определён в:
-
getв интерфейсеFuture<T> - Возвращает:
- вычисленный результат
- Выбрасывает:
-
CancellationException- если вычисление было отменено -
InterruptedException- если текущий поток был прерван во время ожидания -
ExecutionException- если при вычислении возникло исключение
get
public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
Дополнительные сведения см. в описании метода get().
- Определён в:
-
getв интерфейсеFuture<T> - Параметры:
-
timeout- максимальное время ожидания -
unit- единица измерения времени ожидания - Возвращает:
- вычисленный результат
- Выбрасывает:
-
CancellationException- если вычисление было отменено -
InterruptedException- если текущий поток был прерван во время ожидания -
ExecutionException- если при вычислении возникло исключение -
TimeoutException- если время ожидания истекло
addPropertyChangeListener
public final void addPropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener в список слушателей. Слушатель регистрируется для всех свойств. Один и тот же объект слушателя можно добавлять несколько раз; в этом случае он будет вызываться столько раз, сколько был добавлен. Если listener равен null, исключение не выбрасывается и никаких действий не выполняется. Примечание: это лишь вспомогательный метод. Вся работа делегируется PropertyChangeSupport из getPropertyChangeSupport().
- Параметры:
-
listener- добавляемыйPropertyChangeListener
removePropertyChangeListener
public final void removePropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener из списка слушателей. Удаляется PropertyChangeListener, зарегистрированный для всех свойств. Если listener был добавлен к одному и тому же источнику событий несколько раз, после удаления он будет получать на одно уведомление меньше. Если listener равен null или никогда не добавлялся, исключение не выбрасывается и никаких действий не выполняется. Примечание: это лишь вспомогательный метод. Вся работа делегируется PropertyChangeSupport из getPropertyChangeSupport().
- Параметры:
-
listener- удаляемыйPropertyChangeListener
firePropertyChange
public final void firePropertyChange(String propertyName, Object oldValue, Object newValue)
old и new равны и не равны null. Источником всех сгенерированных событий будет этот SwingWorker.
При вызове вне потока обработки событий уведомления PropertyChangeListeners отправляются асинхронно в потоке обработки событий.
Примечание: это лишь вспомогательный метод. Вся работа делегируется PropertyChangeSupport из getPropertyChangeSupport().
- Параметры:
-
propertyName- программное имя изменённого свойства -
oldValue- прежнее значение свойства -
newValue- новое значение свойства
getPropertyChangeSupport
public final PropertyChangeSupport getPropertyChangeSupport()
PropertyChangeSupport для этого SwingWorker. Этот метод используется, когда требуется гибкий доступ к поддержке связанных свойств. Источником всех сгенерированных событий будет этот SwingWorker.
Примечание: возвращаемый PropertyChangeSupport асинхронно уведомляет все PropertyChangeListeners в потоке обработки событий, если вызовы firePropertyChange или fireIndexedPropertyChange выполняются вне потока обработки событий.
- Возвращает:
-
PropertyChangeSupportдля этогоSwingWorker
getState
public final SwingWorker.StateValue getState()
SwingWorker.- Возвращает:
- текущее состояние
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.desktop/javax/swing/SwingWorker.html