4.3运用执行器返回结果
Executor框架的优势之一就是你能够运行并发的任务并且获得对应的结果。Java 并发API完成这个功能是通过下面两个接口:
l Callable: 这个接口有call()方法。在这个方法中,你不得不实现一个任务的逻辑代码。Callable接口是一个参数化的接口,意味着你不得不说明call()方法返回的数据类型。
l Future:这个接口有一些方法去获取由Callable对象产生的结果和管理它的状态。
下面看一个例子,比较好的说明了如何使用Callable和Future类。
import java.util.ArrayList; import java.util.List; //import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; public class FactorialCalculator implements Callable<Integer> { /** * Number to calculate the factorial */ private Integer number; public FactorialCalculator(){ } /** * Constructor of the class. Initializes the attributes * @param number Number to calculate the factorial */ public FactorialCalculator(Integer number){ this.number=number; } /** * Method called by the executor to execute this task and calculate the factorial of a * number */ @Override public Integer call() throws Exception { int num, result; num=number.intValue(); result=1; // If the number is 0 or 1, return the 1 value if ((num==0)||(num==1)) { result=1; } else { // Else, calculate the factorial for (int i=2; i<=number; i++) { result *= i; Thread.sleep(20); } } System.out.printf("%s: %d\n",Thread.currentThread().getName(),result); // Return the value return result; } public void invokeCalling(){ // Create a ThreadPoolExecutor with fixed size. It has a maximun of two threads ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(2); // List to store the Future objects that control the execution of the task and // are used to obtain the results List<Future<Integer>> resultList=new ArrayList<Future<Integer>>(); // Create a random number generator // Random random=new Random(); // Create and send to the executor the ten tasks for (int i=0; i<10; i++){ Integer number=new Integer(i); FactorialCalculator calculator=new FactorialCalculator(number); Future<Integer> result=executor.submit(calculator); resultList.add(result); } // Wait for the finalization of the ten tasks do { System.out.printf("Main: Number of Completed Tasks: %d\n" ,executor.getCompletedTaskCount()); int size = resultList.size(); for (int i=0; i<size; i++) { Future<Integer> result=resultList.get(i); System.out.printf("Main: Task %d: %s\n", i, result.isDone()); } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } while (executor.getCompletedTaskCount()<resultList.size()); // Write the results System.out.printf("Main: Results\n"); for (int i=0; i<resultList.size(); i++) { Future<Integer> result=resultList.get(i); Integer number=null; try { number=result.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.printf("Core: Task %d: %d\n",i,number); } // Shutdown the executor executor.shutdown(); } public static void main(String []args){ (new FactorialCalculator()).invokeCalling(); } }运行结果:
pool-1-thread-1: 1
Main: Number of Completed Tasks: 0
pool-1-thread-2: 1
Main: Task 0: true
Main: Task 1: true
Main: Task 2: false
Main: Task 3: false
Main: Task 4: false
Main: Task 5: false
Main: Task 6: false
Main: Task 7: false
Main: Task 8: false
Main: Task 9: false
pool-1-thread-1: 2
pool-1-thread-2: 6
Main: Number of Completed Tasks: 4
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: false
Main: Task 5: false
Main: Task 6: false
Main: Task 7: false
Main: Task 8: false
Main: Task 9: false
pool-1-thread-1: 24
Main: Number of Completed Tasks: 5
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: true
Main: Task 5: false
Main: Task 6: false
Main: Task 7: false
Main: Task 8: false
Main: Task 9: false
pool-1-thread-2: 120
Main: Number of Completed Tasks: 6
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: true
Main: Task 5: true
Main: Task 6: false
Main: Task 7: false
Main: Task 8: false
Main: Task 9: false
pool-1-thread-1: 720
Main: Number of Completed Tasks: 7
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: true
Main: Task 5: true
Main: Task 6: true
Main: Task 7: false
Main: Task 8: false
Main: Task 9: false
pool-1-thread-2: 5040
Main: Number of Completed Tasks: 8
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: true
Main: Task 5: true
Main: Task 6: true
Main: Task 7: true
Main: Task 8: false
Main: Task 9: false
Main: Number of Completed Tasks: 8
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: true
Main: Task 5: true
Main: Task 6: true
Main: Task 7: true
Main: Task 8: false
Main: Task 9: false
pool-1-thread-1: 40320
Main: Number of Completed Tasks: 9
Main: Task 0: true
Main: Task 1: true
Main: Task 2: true
Main: Task 3: true
Main: Task 4: true
Main: Task 5: true
Main: Task 6: true
Main: Task 7: true
Main: Task 8: true
Main: Task 9: false
pool-1-thread-2: 362880
Main: Results
Core: Task 0: 1
Core: Task 1: 1
Core: Task 2: 2
Core: Task 3: 6
Core: Task 4: 24
Core: Task 5: 120
Core: Task 6: 720
Core: Task 7: 5040
Core: Task 8: 40320
Core: Task 9: 362880