Класс SwingWorker<T,V>
- java.lang.Object
-
- javax.swing.SwingWorker<T,V>
- Type Parameters:
-
T— тип результата, возвращаемый этимSwingWorker'sdoInBackgroundиgetметодами -
V— тип, используемый для передачи промежуточных результатов этимSwingWorker'spublishиprocessметодами
- All Implemented Interfaces:
-
Runnable,Future<T>,RunnableFuture<T>
public abstract class SwingWorker<T,V> extends Object implements RunnableFuture<T>
Абстрактный класс для выполнения длительных задач взаимодействия с графическим интерфейсом в фоновом потоке. Несколько фоновых потоков могут использоваться для выполнения таких задач. Однако точная стратегия выбора потока для любой конкретной SwingWorker не определена и не должна использоваться.
При написании многопоточного приложения с использованием Swing необходимо учитывать два ограничения: (см. Многопоточность в Swing для получения более подробной информации):
- Задания, требующие много времени, не должны выполняться в потоке обработки событий. В противном случае приложение станет неотзывчивым.
- Элементы Swing должны быть обработаны только в потоке обработки событий.
Эти ограничения означают, что приложение GUI с интенсивными вычислениями должно иметь как минимум два потока: 1) поток для выполнения длительной задачи и 2) поток обработки событий (EDT) для всех действий, связанных с GUI. Это включает межпоточное взаимодействие, реализация которого может быть сложной.
Класс 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 для выполнения.
- Since:
- 1.6
Вложенные классы
| Модификатор и тип | Класс | Описание |
|---|---|---|
static class |
SwingWorker.StateValue |
Значения для связанного свойства |
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
SwingWorker() |
Создает этот |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
void |
addPropertyChangeListener(PropertyChangeListener listener) |
Добавляет |
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() |
Возвращает связанное свойство состояния |
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
Методы, унаследованные от интерфейса java.util.concurrent.Future
cancel, isCancelled, isDone
Конструкторы
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 ими. Обратите внимание, что безопасно изменять модель таблицы внутри метода 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(),Future.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 в рабочем потоке (worker thread). Есть несколько доступных рабочих потоков (worker threads). В случае, если все рабочие потоки заняты обработкой других SwingWorkers , этот SwingWorker помещается в очередь ожидания.
Примечание: SwingWorker предназначен для выполнения только один раз. Выполнение SwingWorker более одного раза не приведёт к вызову метода doInBackground дважды.
get
public final T get()
throws InterruptedException,
ExecutionException Ждёт завершения вычисления, если необходимо, и возвращает его результат.
Примечание: вызов get на потоке обработки событий (Event Dispatch Thread) блокирует обработку *всех* событий, включая перерисовку, пока это SwingWorker не завершится.
Если вы хотите, чтобы SwingWorker блокировал поток обработки событий (Event Dispatch Thread), рекомендуем использовать модальное диалоговое окно.
Например:
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 будет источником любых сгенерированных событий.
При вызове с вне потока обработки событий (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.
https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/swing/SwingWorker.html