Executor 框架允许您执行并发任务,不需要操心线程的创建和执行。 它提供了 Future 类可用于控制在一个执行者中执行的任一任务的状态及获得其结果。
当您要等待一个任务的结束,您可使用以下2个方法:
这2个方法有一些缺点:
ThreadPoolExecutor 类提供了一个方法允许您发送给执行者一个任务列表并等待此列表中的所有任务完成。
本节的示例代码在 com.elanzone.books.noteeg.chpt4.sect06 package中
Result : 计算结果 POJO 类
Callable<Result> 类: Task
private String name; public Task(String name) { this.name = name; }
@Override public Result call() throws Exception { System.out.printf("%s: Staring\n", this.name); try { long duration = (long) (Math.random() * 10); System.out.printf("%s: Waiting %d seconds for results.\n", this.name, duration); TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } int value = 0; for (int i = 0; i < 5; i++) { value += (int) (Math.random() * 100); } Result result = new Result(); result.setName(this.name); result.setValue(value); System.out.println(this.name + ": Ends"); return result; }
控制类 : Main
ExecutorService executor = (ExecutorService) Executors.newCachedThreadPool();
List<Task> taskList = new ArrayList<>(); for (int i = 0; i < 3; i++) { Task task = new Task("Task" + i); taskList.add(task); }
List<Future<Result>> resultList = null; try { resultList = executor.invokeAll(taskList); } catch (InterruptedException e) { e.printStackTrace(); }
executor.shutdown();
System.out.println("Main: Printing the results"); if (resultList != null) { for (Future<Result> future : resultList) { try { Result result = future.get(); System.out.println(result.getName() + ": " + result. getValue()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }
本例演示了如何用 invokeAll() 方法将一个任务列表发送到一个执行者并等待所有任务完成。 此方法接受一个 Callable 对象列表并返回一个 Future 对象列表。 在结果列表中,一个任务对应一个 Future 对象。第一个 Future 对象对应的是 Callable 对象列表里的第一个任务,依此类推。