我不明白如何有效地使用AsyncRestTemplate进行外部服务调用。关于以下代码:
class Foo {
public void doStuff() {
Future<ResponseEntity<String>> future1 = asyncRestTemplate.getForEntity(
url1, String.class);
String response1 = future1.get();
Future<ResponseEntity<String>> future2 = asyncRestTemplate.getForEntity(
url2, String.class);
String response2 = future2.get();
Future<ResponseEntity<String>> future3 = asyncRestTemplate.getForEntity(
url3, String.class);
String response3 = future3.get();
}
}理想情况下,我希望同时执行所有3个调用,并在它们都完成后处理结果。然而,,,每个外部服务调用都是,而不是,直到get()被调用,但get()被阻塞。那么,这难道不辜负AsyncRestTemplate的目的吗?我还是用RestTemplate吧。
所以我不明白怎么才能让他们同时执行?
发布于 2016-02-09 13:25:33
只需在分派所有异步调用之前,不要调用阻塞get():
class Foo {
public void doStuff() {
ListenableFuture<ResponseEntity<String>> future1 = asyncRestTemplate
.getForEntity(url1, String.class);
ListenableFuture<ResponseEntity<String>> future2 = asyncRestTemplate
.getForEntity(url2, String.class);
ListenableFuture<ResponseEntity<String>> future3 = asyncRestTemplate
.getForEntity(url3, String.class);
String response1 = future1.get();
String response2 = future2.get();
String response3 = future3.get();
}
}您可以在循环中执行分派和 get ,但请注意,当前的结果收集效率很低,因为它将被困在下一个未完成的未来。
您可以将所有的期货添加到一个集合中,并遍历它,测试每个未来的非阻塞isDone()。当该调用返回true时,您可以调用get()。
这样,您的整体结果收集将被优化,而不是按照调用get()的顺序等待下一个缓慢的未来结果。
更好的是,您可以在每个由ListenableFuture返回的AccyncRestTemplate中注册回调(运行时),而不必担心周期性地检查潜在的结果。
发布于 2016-02-10 15:34:09
如果你不用使用'AsyncRestTemplate‘,我建议你用RxJava代替。RxJava zip操作符是您要找的。检查下面的代码:
private rx.Observable<String> externalCall(String url, int delayMilliseconds) {
return rx.Observable.create(
subscriber -> {
try {
Thread.sleep(delayMilliseconds); //simulate long operation
subscriber.onNext("response(" + url + ") ");
subscriber.onCompleted();
} catch (InterruptedException e) {
subscriber.onError(e);
}
}
);
}
public void callServices() {
rx.Observable<String> call1 = externalCall("url1", 1000).subscribeOn(Schedulers.newThread());
rx.Observable<String> call2 = externalCall("url2", 4000).subscribeOn(Schedulers.newThread());
rx.Observable<String> call3 = externalCall("url3", 5000).subscribeOn(Schedulers.newThread());
rx.Observable.zip(call1, call2, call3, (resp1, resp2, resp3) -> resp1 + resp2 + resp3)
.subscribeOn(Schedulers.newThread())
.subscribe(response -> System.out.println("done with: " + response));
}所有对外部服务的请求都将在单独的线程中执行,当最后一次调用完成时,转换函数(例如简单的字符串连接)将被应用,结果(连接的字符串)将从'zip‘发出。
发布于 2016-02-12 11:17:26
我从您的问题中了解到的是,您有一个预定义的异步方法,并且尝试使用RestTemplate类异步调用该方法。
我已经编写了一个方法,它将帮助您异步调用您的方法。
public void testMyAsynchronousMethod(String... args) throws Exception {
// Start the clock
long start = System.currentTimeMillis();
// Kick of multiple, asynchronous lookups
Future<String> future1 = asyncRestTemplate
.getForEntity(url1, String.class);;
Future<String> future2 = asyncRestTemplate
.getForEntity(url2, String.class);
Future<String> future3 = asyncRestTemplate
.getForEntity(url3, String.class);
// Wait until they are all done
while (!(future1 .isDone() && future2.isDone() && future3.isDone())) {
Thread.sleep(10); //10-millisecond pause between each check
}
// Print results, including elapsed time
System.out.println("Elapsed time: " + (System.currentTimeMillis() - start));
System.out.println(future1.get());
System.out.println(future2.get());
System.out.println(future3.get());
}https://stackoverflow.com/questions/35214384
复制相似问题