如何迭代 Future<List> 对象?

zac*_*ode 2 java concurrency multithreading list

我的call()方法的返回值List<Person>。MyCallable 类如下所示:

public class MyCallable implements Callable<List<Person>> {

    public List<Person> call() throws Exception {

           ...
    
           return list;
    }

    public MyCallable(List<Account> accountList) {
        super();
    }
}
Run Code Online (Sandbox Code Playgroud)

下面是我在 CallableFuture 类中编写的代码:

ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
List<Future<List<Person>>> list = new ArrayList<Future<List<Person>>>();
for (int i = 0; i < 20; i++) {
    Callable<List<Person>> worker = new MyCallable(accountList);
    Future<List<Person>> submit = executor.submit(worker);
    for(Future<List<Person>> :list){
        //list.add(submit);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道如何迭代list并添加submit到它。我这样做对吗?

Jas*_*n C 5

几个问题。首先,与其尝试Future在提交每个结果后立即获取结果(如果您这样做,您实际上只是将所有内容序列化并破坏了目的),而是提交所有结果,然后检索结果:

List<Future<List<Person>>> list = new ArrayList<Future<List<Person>>>();
for (int i = 0; i < 20; i++) {
    Callable<List<Person>> worker = new MyCallable(accountList);
    Future<List<Person>> submit = executor.submit(worker);
    list.add(submit); // just keep track of them
}

// NOW the next step is to get the results...
Run Code Online (Sandbox Code Playgroud)

接下来,您会遇到一些基本的语法问题。一般来说,要遍历容器中的项目,语法是:

List<A> list = ...;

for (A a : list) {
   // do things with 'a'
}
Run Code Online (Sandbox Code Playgroud)

最后,您需要检查 的文档Future,它向您展示了如何等待它被计算并使用Future#get().

将所有这些放在一起,您最终会进入下一步(在如上所述提交所有内容之后):

// ... all tasks submitted and 'list' now contains the Futures, next step:

for (Future<List<Person>> future : list) {
    List<Person> result = future.get(); // wait for task to complete
    // 'result' is now the List<Person> returned from the corresponding callable.
}
Run Code Online (Sandbox Code Playgroud)

提交所有内容然后获得所有结果背后的想法是,您现在允许您的任务并发执行,而不是等待每个任务完成后再添加下一个。然后,最后,即使您最终等待了几个,也没关系,因为所有任务的等待时间已按预期减少。