使用超时阻塞 ListenableFuture
Blocking on ListenableFuture with timeout
我正在使用 Spring 4.2.3 AsyncRestTemplate.exchange() 来调用一些 API,这将需要几秒钟,我希望 listenableFuture.get( 1、TimeUnit.SECONDS)会阻塞1秒然后抛出TimeOutException.
相反,listenableFuture.get() 将在 api 调用的整个过程中阻塞(超过 1 秒)
AsyncRestTemplate restTemplate = new AsyncRestTemplate();
ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.exchange(URL, HttpMethod.GET, null, String.class);
log.debug("before callback");
//...add callbacks
try{
log.debug("before blocking");
listenableFuture.get(1, TimeUnit.SECONDS);
}catch (InterruptedException e) {
log.error(":GOT InterruptedException");
} catch (ExecutionException e) {
log.error(":GOT ExecutionException");
} catch (TimeoutException e) {
log.info(":GOT TimeoutException");
}
log.info("FINISHED");
输出:
09:15:21.596 DEBUG [main] org.springframework.web.client.AsyncRestTemplate:78 - Created asynchronous GET request for "http://localhost:4567/oia/wait?seconds=5"
09:15:21.666 DEBUG [main] org.springframework.web.client.RestTemplate:720 - Setting request Accept header to [text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*]
09:15:21.679 DEBUG [main] com.zazma.flow.utils.FutureTest:74 - before callback
09:15:21.679 DEBUG [main] com.zazma.flow.utils.FutureTest:95 - before blocking
09:15:26.709 DEBUG [main] org.springframework.web.client.AsyncRestTemplate:576 - Async GET request for "http://localhost:4567/oia/wait?seconds=5" resulted in 200 (OK)
09:15:26.711 DEBUG [main] org.springframework.web.client.RestTemplate:101 - Reading [java.lang.String] as "text/html;charset=utf-8" using [org.springframework.http.converter.StringHttpMessageConverter@3a44431a]
09:15:26.717 INFO [main] com.zazma.flow.utils.FutureTest:105 - FINISHED
这是一个示例,当 ListenableFuture.get() 不是由 AsyncRestTemplate
创建时,它将按预期工作
SimpleAsyncTaskExecutor te = new SimpleAsyncTaskExecutor();
ListenableFuture<String> lf = te.submitListenable(() -> {
Thread.sleep(8000);
return "OK";
});
lf.get(1, TimeUnit.SECONDS);
您的代码完全正确。导致问题的原因是 spring 框架中的错误。虽然,我没能在 spring 的问题跟踪器中找到它(或者它可能没有记录),您可以通过更新依赖项来修复它。当然,您的代码将适用于 spring-web >= 4.3.2.RELEASE.
的版本
我正在使用 Spring 4.2.3 AsyncRestTemplate.exchange() 来调用一些 API,这将需要几秒钟,我希望 listenableFuture.get( 1、TimeUnit.SECONDS)会阻塞1秒然后抛出TimeOutException.
相反,listenableFuture.get() 将在 api 调用的整个过程中阻塞(超过 1 秒)
AsyncRestTemplate restTemplate = new AsyncRestTemplate();
ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.exchange(URL, HttpMethod.GET, null, String.class);
log.debug("before callback");
//...add callbacks
try{
log.debug("before blocking");
listenableFuture.get(1, TimeUnit.SECONDS);
}catch (InterruptedException e) {
log.error(":GOT InterruptedException");
} catch (ExecutionException e) {
log.error(":GOT ExecutionException");
} catch (TimeoutException e) {
log.info(":GOT TimeoutException");
}
log.info("FINISHED");
输出:
09:15:21.596 DEBUG [main] org.springframework.web.client.AsyncRestTemplate:78 - Created asynchronous GET request for "http://localhost:4567/oia/wait?seconds=5"
09:15:21.666 DEBUG [main] org.springframework.web.client.RestTemplate:720 - Setting request Accept header to [text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+json, */*]
09:15:21.679 DEBUG [main] com.zazma.flow.utils.FutureTest:74 - before callback
09:15:21.679 DEBUG [main] com.zazma.flow.utils.FutureTest:95 - before blocking
09:15:26.709 DEBUG [main] org.springframework.web.client.AsyncRestTemplate:576 - Async GET request for "http://localhost:4567/oia/wait?seconds=5" resulted in 200 (OK)
09:15:26.711 DEBUG [main] org.springframework.web.client.RestTemplate:101 - Reading [java.lang.String] as "text/html;charset=utf-8" using [org.springframework.http.converter.StringHttpMessageConverter@3a44431a]
09:15:26.717 INFO [main] com.zazma.flow.utils.FutureTest:105 - FINISHED
这是一个示例,当 ListenableFuture.get() 不是由 AsyncRestTemplate
创建时,它将按预期工作SimpleAsyncTaskExecutor te = new SimpleAsyncTaskExecutor();
ListenableFuture<String> lf = te.submitListenable(() -> {
Thread.sleep(8000);
return "OK";
});
lf.get(1, TimeUnit.SECONDS);
您的代码完全正确。导致问题的原因是 spring 框架中的错误。虽然,我没能在 spring 的问题跟踪器中找到它(或者它可能没有记录),您可以通过更新依赖项来修复它。当然,您的代码将适用于 spring-web >= 4.3.2.RELEASE.
的版本