【问题标题】:Thread wait until a set of async tasks are finished线程等待直到一组异步任务完成
【发布时间】:2015-08-12 21:28:11
【问题描述】:

我有一组 HTTP 请求,每个响应都会向 ArrayList 添加一个条目。后来我使用该列表进行一些检查。 如何让程序等到所有请求都完成并且列表已填满后再继续检查?


编辑

代码示例:

class BackgroundTask extends AsyncTask<Void,String,Void>{

    List<Integer> responses;

    @Override
    protected synchronized Void doInBackground(Void... params) {
        responses= new ArrayList<Integer>();

        for( int i=0; i<10; i++ ){
            restAPI.getNextInt( // SEND HTTP REQUEST
                    new Response.OnSuccess() { // ON SUCCESS CALLBACK
                        @Override
                        public void onResponse(Integer i) {
                            responses.add(i);
                        }}, 
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {

                    }});
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
    }
}

在我的主线程中:

BackgroundTask bt = new BackGroundTask();
bt.execute();
bt.get(10000, TimeUnit.MILLISECONDS); // THIS DOESN'T WAIT
if( bt.responses.contains(10) ){
 ...
}

我之前没有提供代码,因为我正在寻找通用解决方案,而不是特定于我的解决方案


编辑 2

这是我的第二次尝试,但没有成功。我把所有东西都放在主线程中。

final Semaphore sema = new Semaphore(-params.size()+1);
final List<Integer> responses = Collections.synchronizedList(new ArrayList<Integer>());
for( final Param p : params ){
    new Thread(){
        @Override
        public void start(){
            restAPI.nextInt(p, // SEND HTTP REQUEST
                    new Response.OnSuccess() { // ON SUCCESS CALLBACK
                        @Override
                        public void onResponse(Integer i) {
                            System.out.print("aaaaa");
                            sema.release();
                            responses.add(i);
                        }}, 
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            sema.release();
                    }});
        }
    }.start();
}
try {
    sema.acquire();
} catch (InterruptedException e1) {
    e1.printStackTrace();
}
if( responses.contains(10) )  
...

现在发生的事情是 sema.acquire() 中的所有内容都阻塞/停止,并且 aaaaa 永远不会打印。如果我删除 sema.acquire() 然后 aaaaa 打印。
如果这很重要,整个代码都在 AsyncTaskprotected void onPostExecute(Void result) 中...

【问题讨论】:

  • 您是否在单独的线程中运行每个 HTTP 请求?
  • 使用一个 AsyncTask ...
  • @markg 不,我有一个 for 循环可以在 AsyncTask 中的同一线程上发送所有请求
  • 那我想我不明白你怎么不知道所有请求是否都完成了
  • 实际上应该由您提供您正在尝试的代码,而不是 Selvin...

标签: java android http android-asynctask sync


【解决方案1】:

您熟悉信号量吗?基本上,信号量有一个与之关联的数字。假设您有五个 http 请求要发出。您将信号量的编号初始化为 -4。从需要等待列表被填充的主线程中,调用信号量上的获取方法。这将导致线程阻塞(等待),直到信号量的编号值为 1。在每个异步线程中,在异步线程完成将其条目添加到列表后,在信号量上调用“释放”。每次在信号量上调用 release 时,信号量的编号都会增加 1。因此,当所有异步线程完成时,信号量的值将是 1,从而允许主线程继续执行。为了将来参考,在信号量上调用 acquire 会将值递减回零。

import java.util.concurrent.Semaphore;

Semaphore sema = new Semaphore(-4);

for each http request that needs to be made:
  spawn a separate thread to execute this function {
     do http request and insert entry into list
     sema.release();
  }

sema.acquire(); // block main thread until http requests are done
doStuff(); //The list is already filled, do whatever you need to do.

【讨论】:

  • 当我放置一个 Semaphore(0) 或更低时,一切都会停止/阻塞。我不知道可能有什么过错。我对每个 HTTP 请求都有一个线程...
  • 可以在调用 sema.release() 之前放置一个打印语句吗?并确保发布正在执行?您还应该在 sema.acquire() 之前放置一个,以确保它被阻止。
  • 基于只有当你使用0或以下时才会发生的事实,似乎没有调用release。
  • 我在响应回调中添加了一个打印。它没有打印。我从我的主线程中删除了 sema.acquire 并打印出来......我不知道为什么。我使用单独的线程来发送请求。我还想提一下,整个代码都在 AsyncTask 的 onPostExecute() 内。如果这很重要
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-13
  • 2013-05-26
相关资源
最近更新 更多