其他分享
首页 > 其他分享> > Future

Future

作者:互联网

https://zhuanlan.zhihu.com/p/54459770

1.为什么出现future机制?

    常见的线程创建方式:1、直接继承thread2、实现runnable接口,这两种方式都有一个缺陷:在执行任务之后无法获取执行结果

    在java1.5之后就提供了Callable和Future,通过他们可以在执行任务完毕后得到任务的执行结果

    future的模式的核心 思想是能够让主线程将原来需要同步等待的这段时间用来做其他事情(因为可以异步执行结果,所以不用一直等待结果)如图

上图简单的描述了使用Future和不使用Future的区别,不使用Future模式,主线程在invoke完成一些耗时的逻辑操作之后需要等待,这个耗时逻辑在实际应用中是一次RPC调用,可能是一个本地IO操作等,B表达了使用Future模式之后,我们主线程在invoke之后可以立即返回,去做其他的事情,回头再看看刚才提交的invoke有没有结果

2.Future相关的类

    Future是个接口,,future就是对具体的Runnable和callable任务的执行或者执行结果进行取消。查询是否完成,获取结果,必要时,可以通过get方法获取执行结果,该方法会阻塞直到返回任务结果,Future接口里定义的方法

canncel();             boolean            我们可以取消这个执行逻辑,如果这个逻辑已经在执行,提供可选的参数来控制是否取消已经正在执行的逻辑

isCancel();            boolean            我们可以判断执行逻辑的任务是否已经被取消

isDone();              boolean            我们可以判断逻辑是否已经完成

get();                 V                  我们可以获取执行逻辑的执行结果

get(long ,TimeUnit);        V                                 我们可以允许在一定时间内等待结果,如果超过这个时间,会抛出TimeoutException

    FutureTask类是Future的具体实现,FutureTask同时也实现了RunnableFuture接口,RunnableFuture又继承了Runnable,所以FutureTask可作为Runnable被线程执行也可做为Future得到Callable的返回值

3.FutureTask源码分析(见笔记本Java源码分析)

4.例1:模拟一个算法,这个算法需要两个输入,input1和input2,需要经过一个非常耗时的操作才能运算得出,由于算法必须要有两个输入都存在才能输出,所以模仿下这个过程

package futurelearn;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.FutureTask;

/*

* 模拟一个算法,这个算法需要两个输入,input1和input2,需要经过一个非常耗时的

* 操作才能运算得出,由于算法必须要有两个输入都存在才能输出,所以模仿下这个过程

* */

public class TestFutureTask1 {

    public static void main(String[] args) {

        //设置开始时间

         long startTime =  System.currentTimeMillis();

        //input2的创建,用时5s

         FutureTask<Integer> input_futuretask2 =  new FutureTask<Integer>(new Callable<Integer>() {

             @Override

             public Integer call() throws  Exception {

                 Thread.sleep(5000);

                 return 5;

             }

         });

        //任务2启动

         new Thread(input_futuretask2).start();

        //input1的创建,用时1s

         FutureTask<Integer> input_futuretask1 =  new FutureTask<Integer>(new Callable<Integer>() {

             @Override

             public Integer call() throws  Exception {

                 Thread.sleep(1000);

                 return 5;

             }

         });

        //任务1启动

         new Thread(input_futuretask1).start();

         try {

             Integer integer1 =  input_futuretask1.get();

             Integer integer2 =  input_futuretask2.get();

             long endTime =  System.currentTimeMillis();

             System.out.println("用时:"+(endTime-startTime)+"ms 结果:"+(integer1+integer2));

         } catch (InterruptedException e) {

             // TODO Auto-generated catch block

             e.printStackTrace();

         } catch (ExecutionException e) {

             // TODO Auto-generated catch block

             e.printStackTrace();

         }

    }

}

-----------------------------------------------------------------------------------------分割线,输出结果---------------------------------------------------------------------------------------------------------------

用时:5002ms 结果:10

-----------------------------------------------------------------------------------------分割线,结果分析---------------------------------------------------------------------------------------------------------------

这个用时和最长的耗时线程的时间相似,而不是1+5=6秒,说明被异步执行了

5.例2:模拟一个场景,假如突然想做饭,但是没有厨具,也没有食材,网上买厨具,超时买食材(https://www.cnblogs.com/cz123/p/7693064.html

package futurelearn;

 

 

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.FutureTask;

/*

* 模拟一个场景,假如突然想做饭,但是没有厨具,也没有食材,网上买厨具,超时买食材

* */

public class TestFutureTask2 {

    public static void main(String[] args) throws InterruptedException {

        long startTime = System.currentTimeMillis();

        // 第一步 网购厨具

        Callable<cooker> onlineShopping = new Callable<cooker>() {

 

 

            @Override

            public cooker call() throws Exception {

                System.out.println("第一步:下单");

                System.out.println("第一步:等待送货");

                Thread.sleep(5000);  // 模拟送货时间

                System.out.println("第一步:快递送到");

                return new cooker();

            }

            

        };

        FutureTask<cooker> task = new FutureTask<cooker>(onlineShopping);

        new Thread(task).start();

        // 第二步 去超市购买食材

        Thread.sleep(2000);  // 模拟购买食材时间

        foods shicai = new foods();

        System.out.println("第二步:食材到位");

        // 第三步 用厨具烹饪食材

        if (!task.isDone()) {  // 联系快递员,询问是否到货

            System.out.println("第三步:厨具还没到,心情好就等着(心情不好就调用cancel方法取消订单)");

        }

        cooker chuju = null;

        try {

            chuju = task.get();

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        } catch (ExecutionException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        System.out.println("第三步:厨具到位,开始展现厨艺");

        cook(chuju, shicai);

        

        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");

    }

 

 

    private static void cook(cooker chuju, foods shicai) {

        // TODO Auto-generated method stub

        

    }

        

    

    static class cooker{}

    static class foods{}

}

-------------------------------------------------------------------------------------------分割线 结果------------------------------------------------------------------------------------------------------------------

第一步:下单

第一步:等待送货

第二步:食材到位

第三步:厨具还没到,心情好就等着(心情不好就调用cancel方法取消订单)

第一步:快递送到

第三步:厨具到位,开始展现厨艺

总共用时5005ms

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:System,食材,Future,FutureTask,new,厨具
来源: https://blog.csdn.net/qq_40800584/article/details/97787070