Wie kann ich den RestTemplate-Aufruf unterbrechen, sobald mein Thread unterbrochen wird?

Ich muss eine Bibliothek erstellen, in der ich synchrone und asynchrone Funktionen haben werde.

executeSynchronous() - wartet, bis ich ein Ergebnis habe, gibt das Ergebnis zurück.executeAsynchronous() - gibt eine Zukunft sofort zurück, die bei Bedarf bearbeitet werden kann, nachdem andere Dinge erledigt wurden.

Core Logic meiner Bibliothek

Der Kunde wird unsere Bibliothek benutzen und sie durch Weitergeben von @ aufrufeDataKey Builder-Objekt. Wir werden dann eine URL erstellen, indem wir das @ benutzeDataKey object und rufen diesen URL über einen HTTP-Client auf, indem Sie ihn ausführen. Nachdem wir die Antwort als JSON-Zeichenfolge zurückerhalten haben, senden wir diese JSON-Zeichenfolge unverändert an unseren Kunden zurück, indem Sie @ erstelleDataResponse Objekt. Einige Kunden werden @ anrufexecuteSynchronous() und einige könnten @ anrufexecuteAsynchronous() Deshalb muss ich zwei Methoden separat in meiner Bibliothek bereitstellen.

Schnittstelle

public interface Client {

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

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

Und dann habe ich meinDataClient was das oben genannte implementiertClient interface:

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

Einfache Klasse, die die eigentliche Aufgabe ausführt:

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

Als ich anfing, an dieser Lösung zu arbeiten, beendete ich die abgelaufenen Aufgaben nicht. Ich habe dem Client das Timeout gemeldet, aber die Task wird weiterhin im Thread-Pool ausgeführt (möglicherweise belegt sie einen meiner begrenzten 10 Threads für längere Zeit). Also habe ich online recherchiert und herausgefunden, dass ich meine Aufgaben, für die das Zeitlimit abgelaufen ist, stornieren kann, indem ich die Option "Bei Zukunft stornieren" verwende (siehe unten

future.cancel(true);

Aber wenn ich so mache, wie in meiner obigen Lösung gezeigt, dann muss ich alle anderen Ressourcen wie @ schließRestTemplate sobald der Thread unterbrochen wird? Wenn ja, wie würde ich das machen? Können wir auch @ unterbrecheRestTemplate Anrufe? Da ich versucht habe, auf meiner Zukunft abzubrechen, sobald die Aufgabe abgelaufen ist, aber ich denke, mein Thread wurde nicht unterbrochen.

Sollten wir immer die Aufgaben beenden, deren Zeit abgelaufen ist? Wenn wir das nicht tun, was könnte ich dann bewirken? Wird es meine Leistung beeinflussen?

Gibt es eine bessere Lösung für diesen Fall mit meinem aktuellen Setup?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage