2014-12-28 6 views
1

Я в ситуации, когда у меня есть коллекция объектов, и каждый объект должен запускать дорогой метод, который занимает около 5-10 секунд.Весна Параллельное выполнение метода

Как я могу запускать все методы параллельно и периодически проверять статус?

Я пытался использовать @Async аннотацию с будущего ответ, но ничего не изменилось.

public static void populate(String marketId) { 
    //irrelevant code removed 

    List<Company> companies = mongo().find(new Query(c), Company.class); 
    List<Future> futures = new ArrayList<Future>(); 

    for(Company comp : companies) { 
     futures.add(comp.updateData(market)); 
    } 
} 

@Async 
public Future<Boolean> updateData(Market market) { 
    //do my slow logic here 

    return new AsyncResult(false); 

} 

ли ThreadPoolTaskExecutor путь?

ответ

2

Я немного смущен относительно причин, по которым вы используете AsyncResult (а какая реализация ... ejb?). Если я не ошибаюсь, это не сработает так, как (из того, что я знаю) AsyncResult связан с bean-компонентом и @Asyncronous аннотацией, что делает ответ от конкретного метода bean assyncronous. Но если использовать внутри объекта, это будет эффективно последовательным.

Что вам нужно, это нормальное Будущее. Если это так, вам нужно фактически запустить эти фьючерсы в исполнителе, а затем подождать, пока они закончат, вызывая future.get(). Хороший учебник по этому вопросу вы можете найти здесь: http://java.dzone.com/articles/javautilconcurrentfuture

Вы также можете изучить Акку. Модель актера - мой личный фаворит, так как вы можете просто создать кучу работников, рассказать им, что делать, и позволить им сообщать вам, как только они закончили свою работу. Тем не менее это может быть излишним, если у вас есть простая задача под рукой, зависит от вашего стиля.

ExecutorService pool = Executors.newFixedThreadPool(10); 

public static void populate(String marketId) { 
    //irrelevant code removed 

    List<Company> companies = mongo().find(new Query(c), Company.class); 
    List<Future> futures = new ArrayList<Future>(); 

    for(Company comp : companies) { 
     futures.add(comp.updateData(market)); 
    } 

    for(Future future: futures) { 
     future.get() 
    } 
} 

public Future<Boolean> updateData(Market market) { 
    return pool.submit(new Callable<Boolean>() { 
      @Override 
      public Void call() throws Exception { 
       //do your slow stuff here; 
       return false; 
      } 
     }) 

} 

Причина, по которой это имеет смысл, если вам нужно получить фактическое возвращение от этих фьючерсов. Если они недействительны, и вам просто нужен поток для выполнения некоторых побочных эффектов в другом месте, то нет смысла делать это таким образом, и вы можете просто использовать runnables и executor. Нечто похожее на это: wait until all threads finish their work in java

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