Java: отменить выполнение метода службы REST

Я предоставляю Stateless EJB как службу REST. В моем POST-методе я вызываю

Result r = longRunningBusinessMethod();
//return data

Как сделать так, чтобы на стороне клиента можно было отменить выполнение longRunningBusinessMethod()? Я подумал о создании потока для метода и сохранении всех исполняемых потоков в хеш-таблице вместе с идентификатором, чтобы пользователь мог отправить свой идентификатор для завершения потока. Но я уверен, что должно быть лучшее решение. Любая помощь будет оценена.


person User9123    schedule 21.06.2017    source источник


Ответы (2)


Я думаю, что грубый дизайн «ведения таблицы идентификаторов» является хорошей отправной точкой. Вместо того, чтобы завершать поток извне, я бы, вероятно, использовал ExecutorService с пулом потоков, а затем сохранил Map<ID, Future>, чтобы вы могли отменить будущее. (Также следите за тем, чтобы каждое будущее удалялось с карты при успешном завершении или в исключительных случаях.)

Вам также придется реализовать longRunningBusinessMethod так, чтобы он содержал достаточно мест, где он проверяет, был ли он прерван - отмена будущего только устанавливает флаг прерывания в потоке, но фактически не останавливает выполнение кода. Если ваши длительные методы уже выдают InterruptedException, все в порядке. В противном случае вам нужно будет либо добавить несколько фиктивных вызовов, таких как Thread.sleep(1), либо время от времени вручную проверять Thread.interrupted(), а InterruptedException выбрасывать самостоятельно.

person Andrew Rueckert    schedule 21.06.2017
comment
Вот как я это сделаю. И я не знал, что мне пришлось вручную завершить свой поток. Короткий и связанный с этим вопрос: когда я использую Future#get(30, TimeUnit.Seconds), будет ли базовый метод по-прежнему выполняться после того, как было выбрано исключение тайм-аута? - person User9123; 22.06.2017
comment
Когда возникает исключение тайм-аута, базовый метод может все еще выполняться. Это только установит флаг interrupted в потоке, который выполняет ваш longRunningBusinessMethod, поэтому этот код все еще должен быть написан таким образом, чтобы его можно было прервать. - person Andrew Rueckert; 23.06.2017

Прерывание рабочих потоков всегда сложно и в целом не рекомендуется. Один из способов решения этой проблемы — изменить работающий бизнес-метод, чтобы он спрашивал, должен ли он завершить свое выполнение. Например:

public void longRunningBusinessMethod(JobContext context){
   while(someCondition) {
        if(shouldInterrupt(context)){
            log.info("Interrupting longRunningBusinessMethod");
            ...
            <close all the resources and terminate the job>
        }
   }
}

TheshouldInterrupt(context) возьмет контекст задания с идентификатором задания и спросит БД или Кэш, следует ли его прервать. Затем легко изменить значение «shouldInterrup» в БД или кэше для этой конкретной работы через REST API.

person Danylo Zatorsky    schedule 21.06.2017