我正在编写一个需要从某些 Web 服务异步获取数据的 Java API。API 需要具有可移植性,能够在常规 Java SE、Java EE、Android 和 BlackBerry 应用程序中使用,因此我想使用一些本机 Java API 来实现这一点(为了可移植性)。我正在考虑使用 Runnable 接口将每个请求作为单独的线程分派,但我没有太多线程经验,我意识到你需要知道你在做什么才能正确地完成它。
使用 Java 异步完成此功能的最佳方法是什么?
我正在编写一个需要从某些 Web 服务异步获取数据的 Java API。API 需要具有可移植性,能够在常规 Java SE、Java EE、Android 和 BlackBerry 应用程序中使用,因此我想使用一些本机 Java API 来实现这一点(为了可移植性)。我正在考虑使用 Runnable 接口将每个请求作为单独的线程分派,但我没有太多线程经验,我意识到你需要知道你在做什么才能正确地完成它。
使用 Java 异步完成此功能的最佳方法是什么?
您可能想使用 aCachedThreadPool
或FixedThreadPool
in java.util.concurrent
。您将希望将 a 与 aCallable
一起使用Future
,而不是Runnable
因为您希望从 Web 服务调用返回一个值。
一个非常简单的例子:
public class MyAPI {
public class SomeResponse {
int value; // assumes some very basic service returns {"value":123}
}
// assumes spring 3+
@Autowired RestTemplate restTemplate;
ExecutorService pool = ExecutorService.newCachedThreadPool();
Future<SomeResponse> getData(int someId) {
return cachedThreadPool.submit(new Callable() {
public SomeResponse call() {
return restTemplate.getForObject("http://example.com/some/path/{someId}",SomeResponse.class, someId);
}
});
}
}
此类服务的调用者可以.get()
针对未来进行调用以获得未来结果。
你的异步边界在哪里?在代码中,还是在网络中?
如果在代码中,请查看java.util.concurrent.CompletionService
. 这ExecutorCompletionService
将使您在满足许多需求的过程中走得更远。
如果在网络中,您需要为网络请求获取一个 ID,并在稍后使用该 ID 来获取响应。代码中的实际实现并不重要。
如何获得响应?它会被轮询,还是会触发回调?
如果它被轮询,则让请求者检查(可能多次)结果。当它可用时,你就拥有了。
如果是回调,则添加一个接口(不是java关键字,典型的英文用法),完成服务可以在不知道对象细节的情况下使用。让请求者包含(作为请求的一部分)必要的信息,以便用结果回叫请求者。
如果轮询,客户端应该阻塞还是忙等待?通常,阻塞是首选以节省 CPU 资源,但是当无法唤醒请求时Thread
(可能是由于它位于不同的机器上),忙碌等待可能是合乎逻辑的选择。如果您确实忙于等待,请负责任地这样做。每隔一秒左右就让 CPU 内核休眠,这种情况是非常罕见的,当问题不允许这样的中断时,如果没有它,你会增加电费,导致与机器中的其他程序不必要的争用,并且通常是一个电脑中的坏邻居。