我目前正在将用Objective-C编写的网络库移植到Java,我需要向服务器发出异步HTTP请求的功能,而不依赖于任何第三方库(因此,没有Apache依赖项)。我正在使用HTTPUrlConnection
来执行此操作;但是,正如您所知,这是一个同步过程。
我正在尝试使用ExecutorService
和Future<>
结构在此过程中实现并发。我需要使用Callable
而不是Runnable
,因为我需要处理服务器发回给我的响应消息。以下是我正在做的一个小概述:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return postRequest(reqMsg);
}
});
其中reqMsg是请求消息(以XML格式),postRequest方法将响应消息作为String(也以XML格式)返回。现在,为了检索此Callable任务的返回值,我需要使用future.get()
。但是,此方法是阻塞调用,这意味着它会阻止主线程,直到响应可用。这不是我想要的。
我正在将一个iOS应用程序移植到Android,我将使用J2ObjC在这些平台之间建立一个跨平台的共享库。在iOS版本(意味着库的Obj-C版本)中,有完成处理程序处理来自HTTP请求的结果,并且它是异步进行的。遗憾的是,Java使用CompletableFuture在Java 8中引入了这种处理它的回调方式。但是,Android仅支持从API级别24开始的CompletableFuture。我希望能够支持返回Jelly Bean(API 16)的API级别。据我所知,“对于与Android兼容的JAR文件,它只能引用可用作Android的一部分的类以及在JAR本身专门实现的其他类”。您可能会建议使用AsyncTasks;但是,我想在Java网络端处理HTTP请求的并发性,因为这个库很可能在两个平台之间共享。
我已经尝试过明确地使用Threads;然而,当我研究它时,我发现为了使用Callables,你需要使用ExecutorService和Future(另外,似乎有一些与显式创建Threads相关的性能开销 - 尽管我认为&lt; 1000ms的开销是上可接受的)。再次,重申(即 TL:DR ):
我不想依赖第三方库,除非它是绝对必要的。
我无法使用CompletableFuture
,因为我希望我的最低API级别为16。
我不想在Android端用AsyncTasks
处理这种并发性,因为最初,这是在网络库中用CompletionHandler
(Objective-C)处理的。
有没有办法在不阻止的情况下使用Future.get()
? (提醒一下,while循环检查Future.isDone()
也会阻塞主线程。)
答案 0 :(得分:2)
调用Future.get()
是阻止操作,您无法更改。
这里你想要的是在工作完成后获得回调。为此,您根本不必使用Future
。您始终可以Executor.execute()
与Runnable
使用与Callable
完全相同的内容,但不应返回值,而应调用自定义 - 在方法参数中提供 - 使用值进行回调。基本上相当于Java 8中引入的Consumer
接口。
ExecutorService executorService = Executors.newSingleThreadExecutor();
public void execute(YourRequestObject reqMsg, Consumer<String> consumer) {
executorService.execute(new Runnable() {
@Override
public void run() {
String result = postRequest(reqMsg);
consumer.accept(result);
}
});
}
每次都不要创建执行者。只需使用一个执行程序即可完成所有操作。也许是缓存的而不是singleThread的。
请记住,您的回调将在执行程序线程上调用。如果您想更新UI,您需要在UI处理程序上发布帖子。
答案 1 :(得分:0)
你的问题没有多大意义。一方面,您希望在单独的线程中获取数据,但同时在另一个线程中获取数据,而无需等待获取线程完成。
你需要做的是将fetch和“对获取的数据执行任何操作”包装到Runnable中并在单独的线程中运行它。
确保在事件调度线程中更新UI,以防您需要使用获取的数据进行更新。