java核心-多线程-线程类(5)-Callable、Future和FutureTask

  1. 基本概念
    <1>Callable,Callable和Runnable差不多,两者都是为那些其实例可能被另一个线程执行的类而设计的,最主要的差别在于Runnable不会
    返回线程运算结果,Callable可以(假如线程需要返回运行结果)。
    <2>Future,是一个接口表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
    <3>FutureTask是Future的实现类,也可以说是进阶类,优化了Future的一些缺点,比如Future.get会阻塞等等,它提供了对Future的基本实现。
    可使用FutureTask包装Callable或Runnable对象,实现异步处理线程运行结果。FutureTask实现了Runnable和Future(看源码可以看出来),所以也可以
    将FutureTask提交给Executor。一般使用FutureTask代替Future即可。

  2. 使用api

    <1>Callable使用方法

            call()  //类似run()方法
<2>Future使用方法
            cancel(boolean mayInterruptIfRunning)  //取消任务,如果已经完成,返回false
            isCancelled()    //判断是否取消过
            isDone()    //判断是否完成,取消、完成、异常都会返回true
            get()  //获取执行结果,阻塞的 
<3>FutureTask使用方法
            cancel(boolean mayInterruptIfRunning)
            isCancelled()
            done()  //重写它来实现异步处理线程执行结果
            isDone()
            run()
            get()
  1. 使用示例
    Callable+Futrue

    private  static class CallableThread implements Callable<String>{
        @Override
        public String call() throws Exception {
            System.out.println("进入CallableThread的call()方法, 开始睡觉, 睡觉时间为" + System.currentTimeMillis());
            Thread.sleep(10000);
            System.out.println("睡觉结束");
            return "123";
        }
    }

    @Test
    public void test2(){
        ExecutorService executorService = Executors.newCachedThreadPool();
        CallableThread callableThread = new CallableThread();
        long l = System.currentTimeMillis();
        System.out.println("任务提交前时间:" + l);
        Future<String> submit = executorService.submit(callableThread);
        try {
            String s = submit.get();
        }catch (Exception e){
        }
        System.out.println("获取结果的时间:" + (System.currentTimeMillis()-l));
    }

执行结果

    任务提交前时间:1556438172228
    进入CallableThread的call()方法, 开始睡觉, 睡觉时间为1556438172229
    睡觉结束
    获取结果的时间:10006

这里的 Future.get 是阻塞方法 , 会一直等待Callable中线程任务执行完毕,是很低下的效率,
解决方式
1.可以使用FutureTask ,重写done方法
2.循环判断isDone,返回true的时候然后调用get()获取

    Callable+FutureTask,异步处理线程运行结果

    private  static class CallableThread implements Callable<String>{
        @Override
        public String call() throws Exception {
            System.out.println("进入CallableThread的call()方法, 开始睡觉, 睡觉时间为" + System.currentTimeMillis());
            Thread.sleep(10000);
            System.out.println("睡觉结束");
            return "123";
        }
    }
     private class MyFutureTask extends FutureTask<String>{
        public MyFutureTask(Callable callable){
            super(callable);
        }

        //FutureTask任务完成,会回调这个方法
        @Override
        protected void done() {
            System.out.println("执行完调用了done()");
            super.done();
            try {
                String s = this.get();
                System.out.println("任务执行完毕:" + s);
                System.out.println("当前时间:" + System.currentTimeMillis());

            }catch (Exception e){
            }
        }
    }

    @Test
    public  void test3() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        CallableThread callableThread = new CallableThread();
        MyFutureTask myFutureTask = new MyFutureTask(callableThread);
        executorService.submit(myFutureTask);
        System.out.println("主线程执行结束");
        try {
             executorService.shutdown();
            executorService.awaitTermination(12,TimeUnit.SECONDS);
        } catch (Exception e) {
        }finally {
            executorService.shutdownNow();
        }
    }

执行结果

     执行结果如下
                主线程执行结束
                进入CallableThread的call()方法, 开始睡觉, 睡觉时间为1556416923492
                睡觉结束
                执行完调用了done()
                任务执行完毕:123
                当前时间:1556416933493
posted on 2019-04-28 16:03  火枪  阅读(280)  评论(0编辑  收藏  举报