当前位置: 首页 > 知识库问答 >
问题:

如何在我的线程中断时立即中断RestTemplate调用?

呼延河
2023-03-14

我需要使一个库,我将有同步和异步的特点。

  • executesynchronous()-等待得到结果,返回结果。
  • executeAsynchronous()-立即返回一个将来值,如果需要,该将来值可以在其他事情完成后处理。

my Library的核心逻辑

public interface Client {

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

    // for asynchronous
    public Future<DataResponse> executeAsynchronous(DataKey key);
}
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调用吗?因为我试图在任务超时后立即在我的未来上调用cancel,但我想我的线程没有被打断。

共有1个答案

岳玉书
2023-03-14

似乎无法中断或取消对RESTTemplate的调用。即使使用了使用回调的“kludge”,RESTTemplate也可能在内部锁定资源,在调用回调之前等待响应。

当底层套接字可以访问时,可以通过从另一个线程关闭套接字来中止网络I/O。例如,可以启动计时器在超时过后关闭套接字。或者,如果您想要对中断敏感的无限期超时(例如,由于用户按下“取消”按钮),您可以提交一个无限期等待但通过关闭套接字来响应中断的任务。

不幸的是,RESTTemplate的作者似乎没有提供这种功能。

 类似资料:
  • 问题内容: 我需要制作一个具有同步和异步功能的库。 -等到得到结果,然后返回结果。 -立即返回Future,如果需要,可以在完成其他操作后进行处理。 我图书馆的核心逻辑 客户将使用我们的库,他们将通过传递构建器对象来调用它。然后,我们将使用该对象构造一个URL,并通过执行该对象来对该URL进行HTTP客户端调用,并在将响应作为JSON字符串返回给我们之后,通过创建对象将该JSON字符串发送回给我们

  • 问题内容: 我正在学习如何在Android中使用线程,并且为此,我制作了一个播放一系列笔记的小型应用程序。这个想法是,有一个开始按钮和一个结束按钮,(显然)如果您按下开始按钮,它将开始播放音乐,而如果您按下结束按钮,它将停止播放。开始按钮可以正常工作,但是问题是结束按钮不能正常工作。我在找出原因时遇到了麻烦,因此也许有些人可以帮助我。这是代码: 问题答案: 您正在调用正在播放的线程,但此时可能正在

  • 编辑: 主要问题:为什么只有一个线程抛出interruptedexception,而两个线程都阻塞在条件上。await 所以下面的代码只是我创建的一个示例。主要的问题是开发一个生产者-消费者实现,在这个实现中,我必须创建一个模拟类,它产生两种线程:客户线程和厨师线程,这两种线程是基于可重入锁进行同步的。在执行一些操作(客户添加订单,厨师执行服务这些订单)后,我调用客户线程上的join以确保所有订单

  • 问题内容: 使用return by时,如何中断它? 问题答案: 为此,您需要将任务分配给,而不是调用。当您执行此操作时,将返回一个可用于操纵计划任务的a。特别是,您可以调用关联程序来中断当前正在执行的任务(或者,如果该任务尚未开始运行,则完全跳过执行)。 顺便说一句,由返回的对象实际上是个。

  • 我有两个实现Runnable接口的对象,并在单独的线程中执行它们。本质上,在Runnable对象的方法中,我执行一些网络活动,包括调用在等待输入(来自网络)时阻塞的方法。请注意,我没有任何有意的暂停,即调用。任何暂停都是由对可能阻塞的方法的调用引起的。 这些可运行对象在GUI的控制下,因此GUI界面和我希望提供给用户的一个功能是结束执行我的可运行对象的线程的能力,但是我无法理解如何做到这一点。 下