• 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 线程执行完毕!

  • 相关阅读:
    8.用户注销
    7.用户登陆,用户退出,记住用户名和密码
    6.后台验证码-session作用域
    5.验证用户名是否已经被注册:AJAXC请求
    4.前端注册表单验证 && 表单回填
    3.注册后台处理逻辑编写
    HTTP Status 500
    jquery之stop()的用法
    angular.forEach
    jquery如何获取第一个或最后一个子元素?
  • 原文地址:https://www.cnblogs.com/yuandluck/p/9510949.html
Copyright © 2020-2023  润新知