Java线程之FutureTask与Future浅析
一、Future使用
FutureTask是Future和Callable的结合体。传统的代码是这样写的
Future f = executor.submit(new Callable());
然后通过Future来取得计算结果。但是,若开启了多个任务,我们无从知晓哪个任务最先结束。因此,若要实现“当某任务结束时,立刻做一些事情,例如记录日志”这一功能,就需要写一些额外的代码。例如一般的Future使用。
多任务:
1 package zmx.multithread.test.reentrantlock; 2 3 4 import java.util.Random; 5 import java.util.concurrent.Callable; 6 import java.util.concurrent.ExecutionException; 7 import java.util.concurrent.ExecutorService; 8 import java.util.concurrent.Executors; 9 import java.util.concurrent.Future; 10 import java.util.concurrent.FutureTask; 11 import java.util.concurrent.TimeUnit; 12 13 public class T1 { 14 public static void main(String[] args) throws InterruptedException, ExecutionException { 15 16 ExecutorService executor2= Executors.newFixedThreadPool(5); 17 class Task implements Callable<String>{ 18 @Override 19 public String call() throws Exception { 20 21 Random rand = new Random(); 22 TimeUnit.SECONDS.sleep(rand.nextInt(10)); 23 return Thread.currentThread().getName(); 24 } 25 } 26 27 List<Future<String>> results = new ArrayList<Future<String>>(); 28 for(int i=0;i<5;i++){ 29 Future<String> f = executor2.submit(new Task()); 30 results.add(f); 31 } 32 33 boolean flag =true; 34 while(flag) { 35 36 for(Iterator<Future<String>> iter = results.iterator();iter.hasNext();){ 37 Future<String> f =iter.next(); 38 if(f.isDone()){ 39 System.out.println(f.get()); 40 iter.remove(); 41 42 } 43 } 44 if(results.size()==0){ 45 flag =false; 46 } 47 48 } 49 50 System.out.println("执行完毕"); 51 52 executor2.shutdownNow(); 53 54 55 56 } 57 58 }
执行结果:
pool-1-thread-4
pool-1-thread-2
pool-1-thread-1
pool-1-thread-5
pool-1-thread-3
执行完毕
二、FutureTask
上述使用遍历的方式解决多任务结果,但是不是最优的效果,FutureTask正是为此而存在,它有一个回调函数protected void done(),当任务结束时,该回调函数会被触发。因此,只需重载该函数,即可实现在线程刚结束时就做一些事情。
代码如下:
1 public class Test { 2 public static void main(String[] args) { 3 ExecutorService executor = Executors.newCachedThreadPool(); 4 for(int i=0; i<5; i++) { 5 Callable<String> c = new Task(); 6 MyFutureTask ft = new MyFutureTask(c); 7 executor.submit(ft); 8 } 9 executor.shutdown(); 10 } 11 12 } 13 14 class MyFutureTask extends FutureTask<String> { 15 16 public MyFutureTask(Callable<String> callable) { 17 super(callable); 18 } 19 20 @Override 21 protected void done() { 22 try { 23 System.out.println(get() + " 线程执行完毕!~"); 24 } catch (InterruptedException | ExecutionException e) { 25 // TODO Auto-generated catch block 26 e.printStackTrace(); 27 } 28 } 29 30 31 } 32 33 class Task implements Callable<String> { 34 35 @Override 36 public String call() throws Exception { 37 Random rand = new Random(); 38 TimeUnit.SECONDS.sleep(rand.nextInt(12)); 39 return Thread.currentThread().getName(); 40 } 41 }
结果如下:
pool-1-thread-4 线程执行完毕!
pool-1-thread-3 线程执行完毕!
pool-1-thread-5 线程执行完毕!
pool-1-thread-2 线程执行完毕!
pool-1-thread-1 线程执行完毕!