如何并行调用一个返回未来的方法?

时间:2015-12-09 14:57:15

标签: java concurrency future executorservice callable

我有一个异步方法,如下所示调用我的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对象。

3 个答案:

答案 0 :(得分: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的ListenableFuture)来执行异步任务。您仍然可以执行上面所做的操作,或者您可以更改代码以充分利用延续任务。

答案 1 :(得分:0)

您可以调用Executor服务invokeAll方法并向其提交任务列表。 Executor Service将并行执行任务。

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

这与以下相同: 1.在executeSync方法中从for循环并行调用executeAsync。 2.在executeSync方法中从for循环顺序调用executeAsync方法。

答案 2 :(得分:0)

没有理由并行执行它,因为它已经并行运行。您唯一需要的是为每个项调用异步方法,并将结果Future存储在列表中。在此循环结束后,您需要浏览这些Future的列表,并在每个get()上调用var converterStrategies = new Dictionary<Object, IConverter>(); converterStrategies.Add(typeOf(string), new StringConverter(...)); 给出结果。这些结果列表将作为返回值返回。