在AsyncTask中同步两个并发网络调用

时间:2014-03-12 23:28:05

标签: java android multithreading concurrency android-asynctask

我尝试进行多个并发HTTP GET调用,这些调用可能会在不同的时间后返回响应。
获得数据后,我使用它为ListView创建自定义适配器。由于存在NullPointerException的高风险,因此在尝试创建适配器之前,我需要确保所有数据都存在。
HTTP调用目前使用AsyncTask完成,这样可以方便地在后台执行,稍后调用UI线程来更新视图。但它们并不是并发的 - 每个呼叫都是在前一个呼叫结束后执行的。

我正在努力解决的问题是确保所有HTTP调用在创建适配器之前都返回了响应,同时仍保持并发。

有没有办法运行多个并发网络调用,并且在所有并发HTTP调用完成后让onPostExecute方法执行此操作?

或者我是否需要使用更复杂的线程,锁等?

1 个答案:

答案 0 :(得分:4)

如果您不需要HTTP电话'反应

CountDownLatch可能会为您解决问题。您使用计数初始化它,然后在每次HTTP调用后调用countDown(),它会立即返回。在onPostExecute侧,await()阻止countDown()被调用count次。

所以:

  • 使用CountDownLatch构造函数中的HTTP调用数构建AsyncTask
  • 在每次HTTP调用后调用latch.countDown()
  • 调用onPostExecute的线程调用latch.await(),它将阻塞,直到所有上述线程都完成了他们的HTTP调用

如果你需要回复

以上内容将会奏效(每个countDown()await()返回之间会发生之前的关系),但还有另一种方式。

Callable<Response>中换行每个HTTP呼叫,并将其提交给ExecutorService;它会立即返回Future<Response>,然后您可以将其提供给定义onPostExecute的对象。该方法可以获得Response r = future.get()的实际响应,这将阻止直到特定的可调用完成。如果您为所有HTTP调用执行此操作,那么在为每个期货调用futureWhatever.get()之后,您将确保HTTP调用已完成。

这种方法的一个优点是onPostExecute在完成所有HTTP调用之前不必阻塞;它可以取得进展,直到那一刻它需要的那个完成。例如,如果确实如此:

Future callA = httpA.get();
processCallA(callA); // this could take a while
Future callB = httpB.get();
...

...然后只要HTTP调用B已经完成,processCallA就可以完成它,只要HTTP调用A已经完成。