• 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
    
  • 相关阅读:
    Django集成celery发送异步邮件
    Bootstrap表格实现列左右调整大小
    Django通用类视图实现忘记密码重置密码功能
    Django项目使用ckeditor(不使用admin)
    HTML提交form表单后获取返回的数据
    Django后端发送小程序微信模板消息(服务通知)
    Django对接支付宝实现支付宝充值金币功能
    Django全文搜索django-haystack+whoosh+jieba实现中文全文搜索
    Django生成PDF文档显示在网页上以及解决PDF中文显示乱码的问题
    PHP socket 接收 java端口 netty 网络字节序
  • 原文地址:https://www.cnblogs.com/leeethan/p/10784517.html
Copyright © 2020-2023  润新知