2015-08-12 2 views
0

У меня есть набор HTTP-запросов, каждый ответ добавляет запись в ArrayList. Позже я использую этот список, чтобы выполнить некоторые проверки. Как я могу заставить программу ждать, пока все запросы не будут выполнены, и список будет заполнен, прежде чем продолжить проверку?Thread: подождите, пока не будет завершен набор задач async.


EDIT

Пример кода:

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() и ааааа никогда не печатает. Если я удалю sema.acquire(), тогда aaaaa печатает.
Всего код находится в protected void onPostExecute(Void result) в качестве AsyncTask, если это имеет значение ...

+0

Вы используете каждый HTTP-запрос в отдельном потоке? – markg

+0

использовать один AsyncTask ... – Selvin

+0

@markg Нет, у меня есть цикл for для отправки всех запросов в тот же поток в AsyncTask – ApollonDigital

ответ

1

Вы знакомы с семафорами? В основном семафор имеет число, связанное с ним. Допустим, у вас есть пять запросов http. Вы инициализируете число семафора до -4. Из основного потока, который должен дождаться заполнения списка, вызовите метод получения на семафоре. Это заставит поток блокировать (ждать), пока номер семафора не будет иметь значение 1. В каждом из ваших асинхронных потоков вызовите «release» в семафоре после того, как поток асинхронов будет добавлен в список. Каждый раз, когда вы вызываете выпуск на семафоре, число семафора увеличивается на 1. Таким образом, когда все асинхронные потоки завершены, семафор будет иметь значение 1, позволяя продолжить основной поток. Для дальнейшего использования вызов, полученный при семафоре, уменьшит значение до нуля.

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. 
+0

Когда я кладу Семафор (0) или ниже, все останавливается/блокируется. Я не знаю, что может быть виновато. У меня есть поток для каждого HTTP-запроса ... – ApollonDigital

+0

Можете ли вы разместить оператор печати перед вызовом sema.release(); и убедитесь, что релиз выполняется вообще? Вы также должны поставить его перед sema.acquire(), чтобы убедиться, что он заблокирован. –

+0

Исходя из того факта, что это происходит, когда только когда вы используете 0 или ниже, кажется, что релиз не вызывается. –

Смежные вопросы