#javafx #multitasking
#javafx #многозадачность
Вопрос:
Мне нужно использовать a Service
, который запускает a Task
более одного раза (= одно и то же Service
должно выполняться несколько раз параллельно Task
). Я прочитал документацию JavaFX, и, похоже, они говорят, что a Service
может запускать только одну Task
задачу одновременно.
Поэтому, если я дважды вызову start
свой Service
объект, первый Task
, возвращенный его createTask
методом, будет остановлен, как если бы я использовал restart
после первого start
.
Однако это неясно. Как я уже говорил, документация, похоже, говорит об этом. Действительно :
Служба создает и управляет задачей, которая выполняет работу в фоновом потоке.
Обратите внимание, что я мог бы подумать, что они также говорят, что a Service
может Task
запускать несколько задач одновременно. Действительно :
Служба может быть создана декларативно и перезапущена по требованию.
Мой вопрос: если я использую N start
подряд, будет Tasks
ли создано N И БУДЕТ ЛИ ВЫПОЛНЯТЬСЯ КАЖДОЕ ИЗ НИХ?
Ответ №1:
«Если я использую N запусков подряд, будут ли созданы N задач И БУДУТ ЛИ ВЫПОЛНЯТЬСЯ КАЖДАЯ ИЗ НИХ?
Короче говоря, нет.
«Если я
start
дважды вызову свойService
объект …»
Из Javadocs:
public void start()
Запускает эту службу. Для успешного выполнения этого вызова служба должна быть в состоянии ГОТОВНОСТИ.
Поэтому, если вы вызовете start()
второй раз без предварительного вызова reset()
, вы просто получите исключение. Вы можете вызывать только reset()
в том случае, если Service
он не находится в RUNNING
SCHEDULED
состоянии или. Вы можете вызвать restart()
, что приведет сначала к отмене любой текущей задачи, а затем к перезапуску службы. (Это то, что подразумевается в документации, в которой говорится, что «служба может быть перезапущена по требованию».)
Конечным результатом этого является то, что служба не может одновременно выполнять две текущие задачи, поскольку не существует последовательности вызовов, которые могут привести к этой ситуации без вызова IllegalStateException
.
Если вы хотите, чтобы одновременно выполнялось несколько задач, просто создайте их самостоятельно и отправьте исполнителю (или запустите каждую в своем собственном потоке, но предпочтительнее исполнитель):
private final Executor exec = Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
// ...
private void launchTask() {
Task<MyDataType> task = new Task<MyDataType>(){
@Override
protected Something call() {
// do work...
return new MyDataType(...);
}
};
task.setOnSucceeded(e -> { /* update UI ... */ });
task.setOnFailed(e -> { /* handle error ... */ });
exec.execute(task);
}
Комментарии:
1. Чем ты! Вы знаете, могу ли я заставить поток приложения JavaFX ждать состояния службы «УСПЕШНО»? Это позволит мне запускать несколько задач с единственным потоком, когда будет достигнуто это состояние (я знаю: параллелизма не будет … кроме как между последней задачей и потоком приложения JavaFX).
2. Хорошо; документ JFX указывает, что исполнитель может быть добавлен в службу. Как вы думаете, я могу объединить свою службу ее задачу исполнителя, который будет использовать последнюю? (Я бы хотел сохранить свою службу на самом деле)
3. Я совершенно не понимаю, чего вы пытаетесь достичь на данный момент. Если вы хотите, чтобы задачи выполнялись параллельно, вы не можете управлять ими с помощью a
Service
(с или без anExecutor
, что является просто деталью реализации службы). Если вы не хотите, чтобы они выполнялись параллельно, почему бы просто не превратить их в одну выполняемую (или одну задачу)? Если вы хотите, чтобы они выполнялись параллельно, и хотите знать, когда все они будут завершены, используйте aCountDownLatch
в отдельном потоке.4. На самом деле, что я действительно хочу сделать, так это запустить несколько задач одновременно. Я неправильно выразился. Ну, у меня просто есть поток приложения JavaFX, который запускает N с
Task
помощью a,Service
и я хотел бы запустить их все параллельно. Вы сказали мне использовать anExecutor
(aCountDownLatch
было бы неверно, потому что, как вы мне сказали, поток JFXAPP не может ждать). Таким образом, я собираюсь использоватьExecutor
. В коде, который вы опубликовали вместе с theExecutor
, я не нашел связи между theTask
и theExecutor
?5. «Я не нашел связи между
Task
иExecutor
» . Последняя строка кода:exec.execute(task)