zoukankan      html  css  js  c++  java
  • Callable Future 和 FutureTask

    1、基本介绍

         Runnable 是一个接口,在它里面只声明了一个 run()方法,由于 run()方法返回值为 void 类型,所以在执行完任务之后无法返回任何结果。
      Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明 了一个方法,只不过这个方法叫做 call(),这是一个泛型接口,call()函数返回的类型就是传递进来的 V 类型。
      Future 就是对于具体的 Runnable 或者 Callable 任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过 get 方法获取执行结果,该方法会阻塞直到任务返回结果。在Future类中一共有5个方法,如下图所示:

    cancel(boolean mayInterruptIfRunning) 方法:尝试取消任务,如果任务已经完成、已经被取消或由于某些其他原因而无法取消,则此尝试将失败。 如果成功,并且在调用cancel()时此任务尚未开始,则该任务永远不会运行。 如果任务已经开始,则{@code mayInterruptIfRunning}参数确定是否应中断执行该任务的线程以尝试停止该任务。cancel(false)  不会中断已经运行的任务。

    get() 方法:获取线程返回结果,阻塞着获取结果 
    get(long timeout, TimeUnit unit) 方法:获取线程结果时设置等待时长
    isCancelled() 方法:如果此任务在正常完成之前被取消,则返回true,否则返回false
    isDone() 方法:如果此任务完成(无论怎么结束的,如异常结束,取消,正常结束),则返回true

    由于Future 只是一个接口,无法直接用来创建对象使用,因此就有了下面的FutureTask

    三者关系图如下

            如上图:FutureTask 类实现了RunnableFuture 接口,RunnableFuture 继承了Runnable接口和Future 接口。所以它既可以作为Runnable被线程执行,又可以作为Future 得到Callable 的返回值

            比如我们通过一个线程运行Callable,但是Thread 不支持构造方法中传递Callable的实例,所以我们需要通过FutureTask 把一个Callable 包装成Runnable交给Thread去运行,然后再通过这个FutureTask 拿到Callable 运行后的线程返回值。

      要new 一个FutureTask的实例,有两种方法,如下图所示。

    2 代码示例

    • 类说明:Future的基本使用
    package cn.lspj.ch2.future;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /**
     * 类说明:Future的使用
     */
    public class UseFuture {
    
        /**
         * 实现Callable接口,允许有返回值
         */
        private static class UseCallable implements Callable<Integer> {
    
            @Override
            public Integer call() throws Exception {
                System.out.println("Callable 子线程开始计算。。。。。。");
                int num = 0;
                for(int i=0;i<5000;i++){
                    num += i;
                }
                System.out.println("Callable 线程计算结果为 num =" + num);
                return num;
            }
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            UseCallable useCallable = new UseCallable();
            // 包装callable为FutureTask
            FutureTask futureTask = new FutureTask(useCallable);
            new Thread(futureTask).start();
            System.out.println("获取子线程Callable计算返回结果:" + futureTask.get());
        }
    }

    执行结果

    • 类说明:Future的使用,演示在计算过程中中断任务
    package cn.lspj.ch2.future;
    
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /**
     * 类说明:Future的使用,演示在计算过程中中断任务
     */
    public class UseFuture {
    
        /**
         * 实现Callable接口,允许有返回值
         */
        private static class UseCallable implements Callable<Integer> {
    
            @Override
            public Integer call() throws Exception {
                System.out.println("Callable 子线程开始计算。。。。。。");
                int num = 0;
                for(int i=0;i<5000;i++){
                    //判断线程中断标记为状态
                    if(Thread.currentThread().isInterrupted()){
                        System.out.println("Callable 子线程计算任务被中断了。。。。。。。。。。");
                        return null;
                    }
                    Thread.sleep(1);
                    num += i;
                    System.out.println("num=" + num);
                }
                System.out.println("Callable 线程计算结果为 num =" + num);
                return num;
            }
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            UseCallable useCallable = new UseCallable();
            // 包装
            FutureTask futureTask = new FutureTask(useCallable);
            new Thread(futureTask).start();
            Thread.sleep(35);
            Random r = new Random(10);
            if(r.nextInt() > 5){
                System.out.println("获取子线程Callable计算返回结果:" + futureTask.get());
            } else {
                System.out.println("cancle..............");
                futureTask.cancel(true);
            }
        }
    }

    futureTask.cancel()  其实是改变了线程的中断位标记状态,线程的中断还是要自己实现的

    执行结果

    ————————————————

    版权声明:本文为CSDN博主「﹏半生如梦愿梦如真て」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/lspj201007186/java/article/details/106247283

  • 相关阅读:
    SIP 研究 API中文
    关于“ARC forbids explicit message send of release”错误
    Android获取屏幕尺寸和密度
    ScrollView 判断滑动到底部
    搭建JAVA版的webService
    MTK 开发
    android 2D动画实现
    android notification详解
    android 监听电话来去电
    SharePoint
  • 原文地址:https://www.cnblogs.com/hup666/p/13055990.html
Copyright © 2011-2022 走看看