Нет никаких причин, чтобы заняться ожиданием завершения Task
.A Task
предоставляет множество способов регистрации обратных вызовов, когда он достигает определенного значения State
.Один из этих механизмов использует EventHandler
s и различные свойства (например, onSucceeded
, onFailed
и т. Д.).Вы также можете прослушивать любое из соответствующих Worker
свойств (например, state
, value
, exception
и т. Д.).
Task<?> task = ...;
task.setOnSucceeded(event -> {
// Do what needs to be done...
});
task.setOnFailed(event -> {
// Do what needs to be done...
});
// execute task on background thread
Обработчики событий и / или прослушиватели свойстввсегда вызывается в потоке приложений JavaFX .
Поскольку вы создаете анонимный класс, вы также можете переопределить защищенные методы Task
;эти методы также вызываются в потоке приложений JavaFX .
Task<Integer> task = new Task<>() {
@Override
protected Integer call() throws Exception {
// background work...
}
@Override
protected void succeeded() {
// do what needs to be done
}
@Override
protected void failed() {
// do what needs to be done
}
}
Примечание. Если вы переопределяете эти методы в ScheduledService
, убедитесь, что при необходимости вызывается супер-реализация,См. Javadoc для получения дополнительной информации.
Есть несколько способов запустить следующий Task
только после завершения предыдущего.Один из них - использовать один поток для запуска всех Task
и поставить их в очередь.
ExecutorService executor = Executors.newSingleThreadExecutor();
for (String s : _userDatabase.getSelectedNames()) {
Task<Integer> task = ...;
// add callbacks to task if necessary
executor.execute(task);
}
executor.shutdown();
Другой вариант - использовать Iterator
.Один пример:
private void execute(final List<String> names, final Executor executor,
final Consumer<Task<Integer>> onNewTask) {
Objects.requireNonNull(names);
Objects.requireNonNull(executor);
Objects.requireNonNull(onNewTask);
if (names.isEmpty()) {
return;
}
final Iterator<String> iterator = names.iterator();
class TaskImpl extends Task<Integer> {
private final String name;
private TaskImpl(String name) {
this.name = name;
}
@Override
protected Integer call() throws Exception {
// background work...
}
@Override protected void succeeded() { complete(); }
@Override protected void failed() { complete(); }
// @Override protected void cancelled() { complete(); }
private void complete() {
if (iterator.hasNext()) {
TaskImpl task = new TaskImpl(iterator.next());
onNewTask.accept(task);
executor.execute(task);
}
}
}
// launch first task
TaskImpl firstTask = new TaskImpl(iterator.next());
onNewTask.accept(firstTask);
executor.execute(firstTask);
}
Третий вариант - сделать всю работу за один Task
.По сути, поместите петлю for
в метод call()
.