我有一组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
如果重要的话,整个代码都在protected void onPostExecute(Void result)
AsyncTask
中......
答案 0 :(得分:1)
你熟悉信号量吗?基本上信号量有一个与之相关的数字。假设您有五个http请求。您将信号量的数字初始化为-4。从需要等待列表填充的主线程中,调用信号量上的acquire方法。这将导致线程阻塞(等待),直到信号量的值为1.在每个异步线程中,在完成异步线程并将其条目添加到列表后,在信号量上调用“release”。每次在信号量上调用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.