Как получить результат следующего запуска задания, которое может быть отменено?
Настройка
У меня есть тяжелый org.eclipse.core.runtime.jobs.Job, который обрабатывает данные из «Источника» и сохраняет их в «Результате».
Код: Выделить всё
private volatile Object source, result;
private static final class SyncJob extends Job {
@Override
public void run(IProgressMonitor monitor) {
result = process(source, monitor);
}
}
Код: Выделить всё
void handleEvent() {
source = data;
syncJob.cancel();
syncJob.schedule();
}
Проблема
А новое требование — получить «Результат» для определенного «нового события» (в том смысле, что нам нужен результат процесса (источник, монитор) для заданного значения источника или для значения, которое было ему присвоено позже заданного значения, точное значение не важно, но оно должно быть «новее», чем то, которое создается в «newEvent»). Дополнительная сложность заключается в том, что это конкретное событие должно обрабатываться синхронно.
Решение 1
Наивным решением было бы следующее:
Код: Выделить всё
void handleNewEvent() {
source = data;
syncJob.cancel();
syncJob.schedule();
syncJob.join();
copy = result; // latest result?
}
- любое другое событие отменяет выполнение задания из другого потока, а затем «Результат» будет устаревшим, поскольку метод join() завершится, даже если задание будет перепланировано
или предыдущий вызов задания завершится, несмотря на то, что он был отменен, по той же причине
Чтобы устранить эти проблемы, я пытаюсь:
Код: Выделить всё
void handleEvent() {
synchronized(syncJob) {
source = data;
syncJob.cancel();
syncJob.schedule();
}
}
void handleNewEvent() {
synchronized(syncJob) {
source = data;
syncJob.cancel();
syncJob.schedule();
}
for (;;) {
syncJob.join();
synchronized(syncJob) {
if (job.getState() == Job.NONE) { // can this happen before before last completion?
break;
}
}
}
copy = result; // latest result?
}
Решение 3
Другой вариант — обнаружить завершение, установив флаг после процесса():
Код: Выделить всё
private volatile Object source, result;
private volatile boolean completed = false;
private static final class SyncJob extends Job {
@Override
public void run(IProgressMonitor monitor) {
result = process(source, monitor);
completed = true;
}
@Override
public boolean shouldSchedule() {
completed = false;
return true;
}
}
void handleNewEvent() {
synchronized(syncJob) {
source = data;
syncJob.cancel();
syncJob.schedule();
}
for (;;) {
syncJob.join();
if (completed) { // will this ever happen?
break;
}
}
copy = result;
}
Я мог бы объединить несколько подходов, добавить прослушиватели заданий и проверьте getResult() задания, но я не чувствую, что достиг надежного решения.
Каков реальный и практический способ получить «Результат»? из данных определенного события с поддержкой отмены и перезапуска?
Подробнее здесь: https://stackoverflow.com/questions/791 ... n-of-a-job
Мобильная версия