我有以下ExecutorService代码。
try{
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Callable<String>> taskList = new ArrayList<Callable<String>>(5);
for(int i=1;i<=5;i++){
taskList.add(new SimpleTask());
}
List<Future<String>> list = executor.invokeAll(taskList);
executor.shutdown();
System.out.println(list.get(0).get());
System.out.println("Exit");
}catch(Exception e){
e.printStackTrace();
}
class SimpleTask implements Callable<String> {
@Override
public String call() throws Exception {
return new Date().toString();
}
}
我想知道list.get(0).get()
会等待所有任务完成吗?
答案 0 :(得分:4)
此处代码不会在执行list.get(0).get()
语句时等待,而是executor.invokeAll(taskList)
语句,因为invokeAll()
方法本身将等待所有线程的复杂化。
了解详情Answer
答案 1 :(得分:1)
是Future get()方法阻止执行并在继续之前等待结果。
get()如果需要等待计算完成,然后 检索其结果。
因此,您的代码list.get(0).get()
将等待任务的执行,然后将其打印出来。但这仅适用于第一个任务,因为您只为列表中的第一个Future调用get()方法。如果您想等待所有任务,您应该遍历列表。
您可以通过修改代码来测试:
public class HelloWorld
{
public static void main(String[] args)
{
try{
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Callable<String>> taskList = new ArrayList<Callable<String>>(5);
for(int i=1;i<=5;i++){
taskList.add(new SimpleTask(i!=1));
}
System.out.println("Before:"+new Date().toString());
List<Future<String>> list = executor.invokeAll(taskList);
executor.shutdown();
System.out.println(list.get(0).get()); //Change that to 1 to see the difference
System.out.println("Exit");
}catch(Exception e){
e.printStackTrace();
}
}
}
class SimpleTask implements Callable<String> {
boolean wait=false;
public SimpleTask(boolean wait){
this.wait=wait;
}
public String call() throws Exception {
if(wait){
Thread.sleep(5000);
}
return ""+wait+" - "+new Date().toString();
}
}
通过向除第一个和正在运行的所有任务添加延迟,您可以看到
运行程序时System.out.println(list.get(0).get());
执行相同的秒。如果你做System.out.println(list.get(1).get());
- &gt;它在5秒后执行。这可以告诉你第一个get(0)只等待第一个执行的未来
答案 2 :(得分:0)
不,代码不会等待每个任务完成。通过调用list.get(0).get()
,您将检索其上的第一个可选调用get()
,该调用将根据documentation阻止该线程。
要等待每个callable完成,您需要遍历列表并查看是否所有都已完成。当然你可以通过在每一个上调用get()
来做到这一点但是你会一直阻塞你的主线程。在等待其他线程执行时,我自己更愿意做某事。
使用Java 8流的示例:
// filter if any future is not done yet
while ( list.stream().anyMatch(i->!i.isDone()) )
{
// Do whatever you want parallel to the evaluation of the Future objects
// example
System.err.println( "Not all are done yet." );
}
// process your results
// example:
String[] results = list.stream().map( Main::evalGet ).toArray(String[]::new);
注意:priavte static <T> TevalGet(Future<T> fu)
只是一个包装函数,用于保持lambda表达式对异常处理的清除,看起来与此类似:
private static <T> T evalGet( Future<T> fu )
{
T obj = null;
try
{
obj = fu.get();
}
catch ( InterruptedException | ExecutionException e )
{
e.printStackTrace();
}
return obj;
}