¿Cómo puedo finalizar las tareas que han excedido el tiempo de espera en subprocesos múltiples?

Necesito hacer una biblioteca en la que tenga métodos sincrónicos y asincrónicos.

executeSynchronous() - espera hasta que tenga un resultado, devuelve el resultado.executeAsynchronous() - devuelve un Futuro inmediatamente que puede procesarse después de que se hagan otras cosas, si es necesario.

Lógica central de mi biblioteca

El cliente usará nuestra biblioteca y la llamará pasandoDataKey objeto constructor Luego construiremos una URL usando eseDataKey objetar y hacer una llamada de cliente HTTP a esa URL ejecutándola y después de que recibamos la respuesta como una cadena JSON, enviaremos esa cadena JSON a nuestro cliente tal como está creandoDataResponse objeto. Algún cliente llamaráexecuteSynchronous() y algunos podrían llamarexecuteAsynchronous() por eso necesito proporcionar dos métodos por separado en mi biblioteca.

Interfaz:

public interface Client {

    // for synchronous
    public DataResponse executeSynchronous(DataKey key);

    // for asynchronous
    public Future<DataResponse> executeAsynchronous(DataKey key);
}

Y luego tengo miDataClient que implementa lo anteriorClient interfaz:

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;
    }
}

Clase simple que realizará la tarea real:

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;
    }
}

Planteamiento del problema:-

Cuando comencé a trabajar en esta solución, no estaba terminando las tareas que se habían agotado. Estaba informando el tiempo de espera al cliente, pero la tarea continúa ejecutándose en el grupo de subprocesos (potencialmente ocupando uno de mis 10 subprocesos limitados durante mucho tiempo). Así que investigué un poco en línea y descubrí que puedo cancelar mis tareas que se han agotado usandocancel enfuture Como se muestra abajo -

future.cancel(true);

Pero quería asegurarme, ¿se ve bien como lo estoy haciendo en miexecuteSynchronous método para cancelar las tareas que han agotado el tiempo de espera?

Ya que estoy llamandocancel() sobre elFuture lo que impedirá que se ejecute si las tareas aún están en la cola, así que no estoy seguro de lo que estoy haciendo es correcto o no. ¿Cuál es el enfoque correcto para hacer esto?

Si hay una mejor manera, ¿alguien puede dar un ejemplo para eso?

Respuestas a la pregunta(1)

Su respuesta a la pregunta