Класс SwingWorker<T,V>
- java.lang.Object
-
- javax.swing.SwingWorker<T,V>
- Type Parameters:
-
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 class |
SwingWorker.StateValue Значения для связанного свойства |
Конструкторы
| Конструктор и описание |
|---|
SwingWorker() Создаёт этот |
Методы
| Модификатор и тип | Метод и описание |
|---|---|
void |
addPropertyChangeListener(PropertyChangeListener listener) Добавляет |
boolean |
cancel(boolean mayInterruptIfRunning) Попытка отменить выполнение этой задачи. |
protected abstract T |
doInBackground() Вычисляет результат или выбрасывает исключение, если это невозможно. |
protected void |
done() Выполняется в потоке обработки событий после завершения метода |
void |
execute() Планирует выполнение этого |
void |
firePropertyChange(String propertyName,
Object oldValue,
Object newValue) Сообщает о обновлении связанного свойства любым зарегистрированным слушателям. |
T |
get() Ждёт, если необходимо, завершения вычислений и возвращает результат. |
T |
get(long timeout,
TimeUnit unit) Ждёт, если необходимо, не более заданного времени завершения вычислений и возвращает результат, если он доступен. |
int |
getProgress() Возвращает связанное свойство |
PropertyChangeSupport |
getPropertyChangeSupport() Возвращает |
SwingWorker.StateValue |
getState() Возвращает связанное свойство состояния |
boolean |
isCancelled() Возвращает |
boolean |
isDone() Возвращает |
protected void |
process(List<V> chunks) Получает части данных из метода |
protected void |
publish(V... chunks) Отправляет фрагменты данных в метод |
void |
removePropertyChangeListener(PropertyChangeListener listener) Удаляет |
void |
run() Устанавливает это |
protected void |
setProgress(int progress) Устанавливает связанное свойство |
Методы, унаследованные от класса java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait Конструкторы
SwingWorker
public SwingWorker()
Создаёт этот SwingWorker.
Методы
doInBackground
protected abstract T doInBackground()
throws Exception Вычисляет результат или выбрасывает исключение, если это невозможно.
Обратите внимание, что этот метод выполняется только один раз.
Примечание: этот метод выполняется в фоновом потоке.
- Возвращает:
- вычисленный результат
- Исключения:
-
Exception- если невозможно вычислить результат
run
public final void run()
Устанавливает этот Future в результат вычисления, если он не был отменён.
- Задано:
-
runв интерфейсеRunnable - Задано:
-
runв интерфейсеRunnableFuture<T> - См. также:
Thread.run()
publish
@SafeVarargs protected final void publish(V... chunks)
Отправляет фрагменты данных в метод process(java.util.List<V>). Этот метод следует использовать внутри метода doInBackground для передачи промежуточных результатов для обработки в потоке обработки событий (Event Dispatch Thread) внутри метода process.
Поскольку метод process вызывается асинхронно в потоке обработки событий (Event Dispatch Thread), могут произойти несколько вызовов метода publish до выполнения метода process. Для повышения производительности все эти вызовы объединяются в один вызов с конкатенированными аргументами.
Например:
publish("1");
publish("2", "3");
publish("4", "5", "6"); может привести к: process("1", "2", "3", "4", "5", "6") Пример использования. Этот фрагмент кода загружает табличные данные и обновляет DefaultTableModel этими данными. Обратите внимание, что безопасно изменять tableModel внутри метода process , поскольку он вызывается в потоке обработки событий (Event Dispatch Thread).
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(java.util.List<V>)
process
protected void process(List<V> chunks)
Получает фрагменты данных из метода publish асинхронно в потоке обработки событий (Event Dispatch Thread).
Для получения более подробной информации обратитесь к методу publish(V...).
- Параметры:
-
chunks- промежуточные результаты для обработки - См. также:
publish(V...)
done
protected void done()
Выполняется в потоке обработки событий (Event Dispatch Thread) после завершения метода doInBackground. По умолчанию метод ничего не делает. Подклассы могут переопределять этот метод для выполнения действий завершения в потоке обработки событий (Event Dispatch Thread). Обратите внимание, что вы можете запросить статус внутри реализации этого метода, чтобы определить результат задачи или отменена ли она.
- См. также:
-
doInBackground(),isCancelled(),get()
setProgress
protected final void setProgress(int progress)
Устанавливает свойство progress. Значение должно быть от 0 до 100.
Поскольку уведомления о PropertyChangeListener выполняются асинхронно в потоке обработки событий (Event Dispatch Thread), могут произойти несколько вызовов метода setProgress перед вызовом любых PropertyChangeListeners. Для повышения производительности все эти вызовы объединяются в один вызов с аргументом последнего вызова.
Например, следующие вызовы:
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.isDone() всегда будут возвращать true. Последующие вызовы Future.isCancelled() всегда будут возвращать true, если этот метод возвратил true.
- Задано:
-
cancelв интерфейсеFuture<T> - Параметры:
-
mayInterruptIfRunning-trueесли поток, выполняющий эту задачу, должен быть прерван; в противном случае текущие задачи могут завершиться - Возвращает:
-
falseесли задачу невозможно отменить, обычно потому, что она уже завершена нормально;trueв противном случае
isCancelled
public final boolean isCancelled()
Возвращает true , если эта задача была отменена до нормального завершения.
- Задано:
-
isCancelledв интерфейсеFuture<T> - Возвращает:
-
trueесли эта задача была отменена до завершения
isDone
public final boolean isDone()
Возвращает true , если эта задача завершена. Завершение может быть вызвано нормальным завершением, исключением или отменением — во всех этих случаях этот метод вернёт true.
get
public final T get()
throws InterruptedException,
ExecutionException Ждёт завершения вычислений и возвращает его результат.
Примечание: вызов get в потоке обработки событий (Event Dispatch Thread) блокирует все события, включая перерисовку, до завершения этой SwingWorker.
Если вы хотите, чтобы SwingWorker блокировала поток обработки событий (Event Dispatch Thread), рекомендуется использовать модальное диалоговое окно.
Например:
class SwingWorkerCompletionWaiter extends 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> - Возвращает:
- вычисленный результат
- Исключения:
-
InterruptedException- если текущий поток был прерван во время ожидания -
ExecutionException- если вычисление выбросило исключение
get
public final T get(long timeout,
TimeUnit unit)
throws InterruptedException,
ExecutionException,
TimeoutException Ждёт завершения вычислений в течение заданного времени и возвращает результат, если он доступен.
Для получения более подробной информации обратитесь к get().
- Задано:
-
getв интерфейсеFuture<T> - Параметры:
-
timeout- максимальное время ожидания -
unit- единица измерения времени аргумента таймаута - Возвращает:
- вычисленный результат
- Исключения:
-
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 будет источником любых сгенерированных событий.
Когда вызывается вне потока обработки событий (Event Dispatch Thread), уведомления PropertyChangeListeners посылаются асинхронно в поток обработки событий (Event Dispatch Thread).
Примечание: это просто удобная обёртка. Все операции делегированы PropertyChangeSupport из getPropertyChangeSupport().
- Параметры:
-
propertyName- программное имя свойства, которое было изменено -
oldValue- старое значение свойства -
newValue- новое значение свойства
getPropertyChangeSupport
public final PropertyChangeSupport getPropertyChangeSupport()
Возвращает PropertyChangeSupport для этого SwingWorker. Этот метод используется, когда требуется гибкий доступ к поддержке связанных свойств.
Этот SwingWorker будет источником любых сгенерированных событий.
Примечание: возвращаемый PropertyChangeSupport уведомляет любые PropertyChangeListener асинхронно в потоке обработки событий (Event Dispatch Thread) в случае, если firePropertyChange или fireIndexedPropertyChange вызываются вне потока обработки событий (Event Dispatch Thread).
- Возвращает:
-
PropertyChangeSupportдля этогоSwingWorker
getState
public final SwingWorker.StateValue getState()
Возвращает связанное свойство состояния SwingWorker.
- Возвращает:
- текущее состояние
© 1993, 2020, 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.