Как я могу завершить Задачи, которые истекли в многопоточности?
Мне нужно сделать библиотеку, в которой у меня будут синхронные и асинхронные методы.
executeSynchronous()
- ждет, пока у меня не появится результат, возвращает результат.executeAsynchronous()
- немедленно возвращает Future, который может быть обработан после выполнения других действий, если это необходимо.Основная логика моей библиотеки
Клиент будет использовать нашу библиотеку и позвонит ей, передавDataKey
застройщик объекта. Затем мы создадим URL, используя этоDataKey
выполнить объект и выполнить HTTP-вызов клиента на этот URL, выполнив его, и после того, как мы получим ответ обратно в виде строки JSON, мы отправим эту строку JSON нашему клиенту в том виде, как он есть, создавDataResponse
объект. Какой-то клиент позвонитexecuteSynchronous()
а некоторые могут позвонитьexecuteAsynchronous()
вот почему я должен предоставить два метода отдельно в моей библиотеке.
Интерфейс:
public interface Client {
// for synchronous
public DataResponse executeSynchronous(DataKey key);
// for asynchronous
public Future<DataResponse> executeAsynchronous(DataKey key);
}
И тогда у меня есть мойDataClient
который реализует вышеупомянутоеClient
интерфейс:
public class DataClient implements Client {
private RestTemplate restTemplate = new RestTemplate();
private ExecutorService executor = Executors.newFixedThreadPool(10);
// for synchronous call
@Override
public DataResponse executeSynchronous(DataKey key) {
DataResponse dataResponse = null;
Future<DataResponse> future = null;
try {
future = executeAsynchronous(key);
dataResponse = future.get(key.getTimeout(), TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
PotoLogging.logErrors(ex, DataErrorEnum.TIMEOUT_ON_CLIENT, key);
dataResponse = new DataResponse(null, DataErrorEnum.TIMEOUT_ON_CLIENT, DataStatusEnum.ERROR);
// does this look right the way I am doing it?
future.cancel(true); // terminating tasks that have timed out.
} catch (Exception ex) {
PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
}
return dataResponse;
}
//for asynchronous call
@Override
public Future<DataResponse> executeAsynchronous(DataKey key) {
Future<DataResponse> future = null;
try {
Task task = new Task(key, restTemplate);
future = executor.submit(task);
} catch (Exception ex) {
PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
}
return future;
}
}
Простой класс, который будет выполнять актуальную задачу:
public class Task implements Callable<DataResponse> {
private DataKey key;
private RestTemplate restTemplate;
public Task(DataKey key, RestTemplate restTemplate) {
this.key = key;
this.restTemplate = restTemplate;
}
@Override
public DataResponse call() {
DataResponse dataResponse = null;
String response = null;
try {
String url = createURL();
response = restTemplate.getForObject(url, String.class);
// it is a successful response
dataResponse = new DataResponse(response, DataErrorEnum.NONE, DataStatusEnum.SUCCESS);
} catch (RestClientException ex) {
PotoLogging.logErrors(ex, DataErrorEnum.SERVER_DOWN, key);
dataResponse = new DataResponse(null, DataErrorEnum.SERVER_DOWN, DataStatusEnum.ERROR);
} catch (Exception ex) {
PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
}
return dataResponse;
}
// create a URL by using key object
private String createURL() {
String url = somecode;
return url;
}
}
Постановка задачи:-
Когда я начал работать над этим решением, я не прекращал выполнение заданий, срок действия которых истек. Я сообщал клиенту об истечении времени ожидания, но задача продолжает выполняться в пуле потоков (потенциально занимающих один из моих ограниченных 10 потоков в течение длительного времени). Поэтому я провел некоторые исследования в Интернете и обнаружил, что могу отменить свои задачи, для которых истек срокcancel
наfuture
как показано ниже -
future.cancel(true);
Но я хотел убедиться, выглядит ли это правильно, как я делаю в моемexecuteSynchronous
способ отменить задачи, которые получили тайм-аут?
Так как я звонюcancel()
наFuture
что остановит его выполнение, если задачи все еще находятся в очереди, поэтому я не уверен, что я делаю правильно или нет? Какой правильный подход для этого?
Если есть какой-то лучший способ, то кто-нибудь может привести пример для этого?