Как я могу прервать вызов RestTemplate, как только мой поток будет прерван?

Мне нужно сделать библиотеку, в которой у меня будет синхронная и асинхронная функция.

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 looks right?
            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 потоков в течение длительного времени). Поэтому я провел некоторые онлайн-исследования и обнаружил, что могу отменить свои задачи, для которых истек срок ожидания, с помощью функции «Отмена на будущее», как показано ниже -

future.cancel(true);

Но если я делаю так, как показано в моем решении выше, то мне нужно закрыть другие ресурсы, такие какRestTemplate как только поток прерывается? Если да, то как бы я это сделал? Кроме того, мы можем прерватьRestTemplate звонки? Так как я попытался вызвать отмену в моем будущем, как только истекло время выполнения задачи, но я думаю, что мой поток не прерывался.

Должны ли мы всегда завершать задачи, для которых истекло время ожидания? Если мы этого не сделаем, то какое влияние я окажу? Повлияет ли это на мою производительность?

Есть ли лучшее решение для этого случая с моей текущей настройкой?

Ответы на вопрос(2)

Ваш ответ на вопрос