zoukankan      html  css  js  c++  java
  • Java线程(七):Callable和Future

           接着上一篇继续并发包的学习。本篇说明的是Callable和Future。它俩非常有意思的,一个产生结果。一个拿到结果。


           Callable接口相似于Runnable,从名字就能够看出来了,可是Runnable不会返回结果,而且无法抛出返回结果的异常,而Callable功能更强大一些,被线程运行后,能够返回值。这个返回值能够被Future拿到。也就是说,Future能够拿到异步运行任务的返回值。以下来看一个简单的样例:

    public class CallableAndFuture {
        public static void main(String[] args) {
            Callable<Integer> callable = new Callable<Integer>() {
                public Integer call() throws Exception {
                    return new Random().nextInt(100);
                }
            };
            FutureTask<Integer> future = new FutureTask<Integer>(callable);
            new Thread(future).start();
            try {
                Thread.sleep(5000);// 可能做一些事情
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

           FutureTask实现了两个接口,Runnable和Future,所以它既能够作为Runnable被线程运行。又能够作为Future得到Callable的返回值,那么这个组合的使用有什么优点呢?如果有一个非常耗时的返回值须要计算,而且这个返回值不是立马须要的话,那么就能够使用这个组合,用还有一个线程去计算返回值,而当前线程在使用这个返回值之前能够做其他的操作,等到须要这个返回值时。再通过Future得到,岂不美哉!这里有一个Future模式的介绍:http://openhome.cc/Gossip/DesignPattern/FuturePattern.htm
           以下来看还有一种方式使用Callable和Future,通过ExecutorService的submit方法运行Callable,并返回Future,代码例如以下:

    public class CallableAndFuture {
        public static void main(String[] args) {
            ExecutorService threadPool = Executors.newSingleThreadExecutor();
            Future<Integer> future = threadPool.submit(new Callable<Integer>() {
                public Integer call() throws Exception {
                    return new Random().nextInt(100);
                }
            });
            try {
                Thread.sleep(5000);// 可能做一些事情
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

           代码是不是简化了非常多,ExecutorService继承自Executor,它的目的是为我们管理Thread对象,从而简化并发编程,Executor使我们无需显示的去管理线程的生命周期,是JDK 5之后启动任务的首选方式。
           运行多个带返回值的任务,并取得多个返回值。代码例如以下:

    public class CallableAndFuture {
        public static void main(String[] args) {
            ExecutorService threadPool = Executors.newCachedThreadPool();
            CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);
            for(int i = 1; i < 5; i++) {
                final int taskID = i;
                cs.submit(new Callable<Integer>() {
                    public Integer call() throws Exception {
                        return taskID;
                    }
                });
            }
            // 可能做一些事情
            for(int i = 1; i < 5; i++) {
                try {
                    System.out.println(cs.take().get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }
    } 

           事实上也能够不使用CompletionService,能够先创建一个装Future类型的集合。用Executor提交的任务返回值加入到集合中。最后遍历集合取出数据,代码略。更新于2016-02-05,评论中就这个说法引发了讨论,事实上是我没有讲清楚,抱歉。

    这里再阐述一下:提交到CompletionService中的Future是依照完毕的顺序排列的,这样的做法中Future是依照加入的顺序排列的。

    所以这两种方式的差别就像评论中fishjam所描写叙述的那样。

           本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7451464。转载请注明。

  • 相关阅读:
    ASP.NET CORE 使用Consul实现服务治理与健康检查(2)——源码篇
    ASP.NET CORE 使用Consul实现服务治理与健康检查(1)——概念篇
    Asp.Net Core 单元测试正确姿势
    如何通过 Docker 部署 Logstash 同步 Mysql 数据库数据到 ElasticSearch
    Asp.Net Core2.2 源码阅读系列——控制台日志源码解析
    使用VS Code 开发.NET CORE 程序指南
    .NetCore下ES查询驱动 PlainElastic .Net 升级官方驱动 Elasticsearch .Net
    重新认识 async/await 语法糖
    EF添加
    EF修改部分字段
  • 原文地址:https://www.cnblogs.com/llguanli/p/7272319.html
Copyright © 2011-2022 走看看