2015-12-09 3 views
0

У меня есть метод async, как показано ниже, который вызывает мой класс Task и мой класс Task выполняет всю работу.Как вызвать метод параллельно, который возвращает будущее?

@Override 
    public Future<DataResponse> executeAsync(DataKey key) { 
     Future<DataResponse> future = null; 

     try { 
      Task task = new Task(key, restTemplate); 
      future = executor.submit(task); 
     } catch (Exception ex) { 
      // logging exception here 
     } 

     return future; 
    } 

Ниже мой Task класс, который делает всю работу:

public class Task implements Callable<DataResponse> { 

    private DataKey key; 
    private RestTemplate restTemplate; 

    public Task(DataKey key, RestTemplate restTemplate) { 
     this.key = key; 
     this.restTemplate = restTemplate; 
    } 

    @Override 
    public DataResponse call() throws Exception { 
     // some code here 
    } 
} 

Теперь мне нужно вызвать метод executeAsync параллельно, а затем сделать List<DataResponse> объект и вернуть его.

@Override 
public List<DataResponse> executeSync(DataKey key) { 
    List<DataResponse> responseList = new ArrayList<DataResponse>(); 

    // make a List of DataKey using single key passed to this method.  
    List<DataKey> keys = new ArrayList<DataKey>(); 

    for(DataKey key : keys) { 


    } 
} 

Как я могу назвать executeAsync метод параллельно и вернуться обратно responseList? В моем keys списке максимум у меня будет шесть объектов DataKey.

ответ

1

Если вы ожидаете вернуть List<DataResponse>, содержащий объекты DataResponse, которые были возвращены Task#call, вы не можете сделать это асинхронно. Вам нужно будет заблокировать внутри executeSync, чтобы дождаться результата всех фьючерсов.

List<Future> futures = new ArrayList<>(keys.size()); 
for(DataKey key : keys) { 
    Future<DataResponse> future = executeAsync(key); 
    futures.add(future); 
} 

for (Future<DataResponse> future : futures) { 
    try { 
     responseList.add(future.get()); 
    } catch (Exception e) { 
     // do something else. 
    } 
    return responseList 
} 

Более приемлемым решением с Future является использование CompletionService, как подробно описано here.

В Java 8 вы должны использовать CompletableFuture (или Guava's ListenableFuture) для асинхронных задач. Вы все еще можете сделать то, что я сделал выше, или вы можете изменить свой код, чтобы в полной мере использовать задачи продолжения.

+0

Итак, в этом примере предположим, что у меня есть 3 фьючерса, а затем мы повторяем их в цикле, в блоке try он будет вызывать future.get для первого будущего, а затем он будет ждать, как только это будет завершено, оно вызовет второе второе будущее? – john

+0

Есть ли способ вызвать сразу все методы получения фьючерсов? Я все еще на Java 7. – john

+0

Правильно. 'get' - это блокирующий вызов. 'CompletionService' делает это немного лучше. _call их всех сразу_ будет решением akki, но вы должны изменить некоторые вещи в своем коде, и это фактически делает то же самое внутри. –

0

Вы можете вызвать метод invokeAll службы-исполнителя и отправить ему список задач. Служба-исполнитель будет выполнять задачи параллельно.

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAll(java.util.Collection)

Это было бы так же, как: 1. ссылающегося executeAsync параллельно от для цикла в методе executeSync. 2. вызов метода executeAsync последовательно из цикла for в методе executeSync.

+0

, так что все мои методы получения будущего будут вызываться параллельно? Можете ли вы привести пример, если это возможно? – john

+0

@ david Нет, они не будут вызываться параллельно. Звонки просто скрыты от вас. –

0

Нет причин для его параллельного выполнения, поскольку он уже работает параллельно. Единственное, что вам нужно - это вызвать метод async для каждого из элементов и сохранить результат Future s в списке. По завершении этого цикла вам нужно пройти список тех Future s, и вызов get() на каждом из них даст результат. В этом списке результатов вы вернетесь как возвращаемое значение.

+0

Итак, когда мы звоним в будущее, это будет последовательный звонок? Я имею в виду, что вызов набирает первое будущее, затем второе будущее, а затем третье будущее по одному. Есть ли способ вызвать все фьючерсы сразу получить метод? – john

+0

Это не может быть ничего, кроме последовательного, поскольку вы добавляете результат в список, который представляет собой структуру данных, к которой необходимо получить доступ последовательно. Но эта операция очень быстрая, так как она просто проверяет, завершено ли будущее и сразу же возвращается. Выполнение обычно завершено, как только вы вызываете get. –

+0

Итак, подождите, вы хотите сказать, как только я добавлю все фьючерсы в список, и, прежде чем я позвоню в первое будущее, возможно, он уже был закончен? Если это правда, можете ли вы объяснить это, если это возможно? Все еще учись, чтобы это помогло мне. – john

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