Callable、Future、FutureTask的用法

package cn.com;

import java.util.concurrent.*;

/**
 * Copyright (C), 2018-2019
 * Callable、Future、FutureTask的用法
 * @Description: TODO
 * @Author: zhou
 * @Create: 2019/10/10 17:50
 * @Version 1.0.0
 */

public class ExecutorServiceTest {
    /**
     * Callable、Future 出现的原因:
     *    我们所熟知的创建线程的两种方式,直接继承Thread,或者实现Runnable接口.
     *    对于这两种方式,有个通用的缺陷: 在执行完成任务后无法获取执行结果。
     *    如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。
     *
     *    java 1.5开始,提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
     *
     *    Callable接口代表一段可以调用并返回结果的代码;Future接口表示异步任务,是还没有完成的任务给出的未来结果。
     *    所以说Callable用于产生结果,Future用于获取结果。
     *
     *   Future介绍
     *      在Future接口中声明了5个方法,下面依次解释每个方法的作用:
     *   cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在
     *   执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true
     *   还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则
     *   返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
     *      isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
     *      isDone方法表示任务是否已经完成,若任务完成,则返回true;
     *      get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
     *      get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
     *   也就是说Future提供了三种功能:
     *   1)判断任务是否完成;2)能够中断任务;3)能够获取任务执行结果。
     *   因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。FutureTask是Future唯一实现接口。
     */
    private static String callReturnStr ;
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println(CallableTest());
        RunnableTest();

    }

    public static String CallableTest(){
        ExecutorService executorService = Executors.newFixedThreadPool(1);// 申请一个固定长度的线程池
        try {
            // 创建一个任务,返回一个string
            Callable<String> callable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(200);
                    callReturnStr = Thread.currentThread().getName() + " --CallableTest";
                    return callReturnStr;
                }
            };

            /**
             * 第一种方式:直接使用 ExecutorService的submit返回一个 Future
             */
            //Future<String> future = executorService.submit(callable); // 执行任务
            //callReturnStr = future.get(150, TimeUnit.MILLISECONDS);  // 设置超时时间

            /**
             * 第二种方式:
             */
            FutureTask<String> futureTask = new FutureTask<String>(callable);
            executorService.execute(futureTask);
            callReturnStr = futureTask.get(150, TimeUnit.MILLISECONDS);
            if(futureTask.isDone()){
                System.out.println("执行完成。");
                executorService.shutdown();
            }
        } catch (InterruptedException e) {
            //中端异常处理
            e.printStackTrace();
            callReturnStr = "中端异常处理";
            executorService.shutdown(); // 结束线程
        } catch (ExecutionException e) {
            //线程执行异常处理
            e.printStackTrace();  // 结束线程
            callReturnStr = "线程执行异常处理";
            executorService.shutdown();
        } catch (TimeoutException e) {
            //超时异常处理
            e.printStackTrace();  // 结束线程
            System.out.println("超时异常处理返回结果:" + callReturnStr); // 超时的返回结果
            callReturnStr = "超时异常处理";
            executorService.shutdown();
        }

        return callReturnStr;
    }

    public static void RunnableTest(){
        ExecutorService executorService = Executors.newFixedThreadPool(1);// 申请一个固定长度的线程池
        try {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "--RunnableTest");
                }
            };

            /**
             * ExecutorService接口中声明了若干个submit方法的重载版本
             * submit(Runnable task, T result);
             * 其中 result是自定义的返回结果
             */
            //Future future = executorService.submit(runnable); // 执行任务
            Future future = executorService.submit(runnable, "自定义结果!"); // 执行任务
            future.get(150, TimeUnit.MILLISECONDS);  // 设置超时时间
            if(future.isDone()){
                System.out.println("执行完成。");
                executorService.shutdown();
            }
        }  catch (InterruptedException e) {
            //中端异常处理
            e.printStackTrace();
            callReturnStr = "中端异常处理";
            executorService.shutdown(); // 结束线程
        } catch (ExecutionException e) {
            //线程执行异常处理
            e.printStackTrace();  // 结束线程
            callReturnStr = "线程执行异常处理";
            executorService.shutdown();
        } catch (TimeoutException e) {
            //超时异常处理
            e.printStackTrace();  // 结束线程
            System.out.println("超时异常处理返回结果:" + callReturnStr); // 超时的返回结果
            callReturnStr = "超时异常处理";
            executorService.shutdown();
        }

    }

}

 

参考:https://blog.csdn.net/vking_wang/article/details/9470499

posted @ 2019-10-11 14:41  socketsea  阅读(277)  评论(0)    收藏  举报