我有一组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) ){
...
}
我之前没有提供代码,因为我在寻找通用的解决方案,而不是为我特定的
EDIT 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
如果这是重要的…你熟悉信号量吗?基本上,一个信号量有一个与之相关联的数字。假设您有五个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.