Класс 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 должны обращаться только в потоке обработки событий.
Эти ограничения означают, что приложение 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 для выполнения.
- С:
- 1.6
Краткое описание вложенных классов
| Модификатор и тип | Класс | Описание |
|---|---|---|
static enum |
SwingWorker.StateValue |
Значения для связанного свойства state. |
Вложенные классы/интерфейсы, объявленные в интерфейсе java.util.concurrent.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(java.util.List<V>). |
final void |
removePropertyChangeListener |
Удаляет PropertyChangeListener из списка слушателей. |
final void |
run() |
Устанавливает это Future в результат вычисления, если она не была отменена. |
protected final void |
setProgress |
Устанавливает связанное свойство progress. |
Методы, объявленные в классе java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Методы, объявленные в интерфейсе java.util.concurrent.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(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
protected void process(List<V> chunks)
publish асинхронно в потоке обработки событий (Event Dispatch Thread). Дополнительные сведения см. в методе publish(V...).
- Параметры:
-
chunks- промежуточные результаты для обработки - См. также:
done
protected void done()
doInBackground. По умолчанию ничего не делает. Подклассы могут переопределить этот метод, чтобы выполнить действия завершения в потоке обработки событий (Event Dispatch Thread). Обратите внимание, что вы можете запросить состояние внутри реализации этого метода, чтобы определить результат этой задачи или была ли эта задача отменена.- См. также:
setProgress
protected final void setProgress(int progress)
Поскольку PropertyChangeListener уведомляются асинхронно в потоке обработки событий (Event Dispatch Thread), несколько вызовов метода setProgress могут произойти до вызова любых PropertyChangeListeners. Для повышения производительности все эти вызовы объединяются в один вызов с аргументом последнего вызова.
Например, следующие вызовы:
setProgress(1); setProgress(2); setProgress(3);могут привести к одному уведомлению о прогрессе со значением
3. - Параметры:
-
progress- значение прогресса для установки - Исключения:
-
IllegalArgumentException- если значение не в диапазоне от 0 до 100
getProgress
public final int getProgress()
- Возвращает:
- свойство прогресса.
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
public final boolean isDone()
true , если эта задача завершена. Завершение может быть вызвано нормальным завершением, исключением или отменением — во всех этих случаях этот метод вернёт true. - Определено в:
-
isDoneв интерфейсеFuture<T> - Возвращает:
-
trueесли эта задача завершена
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().
- Parameters:
-
listener- удаляемыйPropertyChangeListener
firePropertyChange
public final void firePropertyChange(String propertyName, Object oldValue, Object newValue)
old и new равны и не равны null. Этот SwingWorker будет источником всех сгенерированных событий.
При вызове с потока обработки событий PropertyChangeListeners уведомляются асинхронно в потоке обработки событий.
Примечание: это всего лишь удобная обертка. Вся работа делегируется PropertyChangeSupport из getPropertyChangeSupport().
- Parameters:
-
propertyName- программное имя изменённого свойства -
oldValue- старое значение свойства -
newValue- новое значение свойства
getPropertyChangeSupport
public final PropertyChangeSupport getPropertyChangeSupport()
PropertyChangeSupport для этого SwingWorker. Этот метод используется, когда необходим гибкий доступ к поддержке связанных свойств. Этот SwingWorker будет источником всех сгенерированных событий.
Примечание: возвращённый PropertyChangeSupport уведомляет всех PropertyChangeListener асинхронно в потоке обработки событий в случае, если firePropertyChange или fireIndexedPropertyChange вызываются вне потока обработки событий.
- Returns:
-
PropertyChangeSupportдля этогоSwingWorker
getState
public final SwingWorker.StateValue getState()
SwingWorker. - Returns:
- текущее состояние
© 1993, 2023, 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/21/docs/api/java.desktop/javax/swing/SwingWorker.html