精华内容
下载资源
问答
  • 请问这个也是自然语言处理器一样受限于<code>short message长度吗? 关于定时任务中断 因为定时任务不易测试(主要因为我调用爬虫API有获取上限)所以想手动命令, 已经把定时...
  • immediate">setTimeout setImmediate 的区别</a></h5> </li><li> <h5><a href="#nexttick">process.nextTick()</a></h5> </li><li> <h5><a href="#nexttick&immediate">process.nextTick() setImmediate()...
  • jdk1.8之前Future模式一个最大的问题是:向线程池提交任务异步执行并获取Future对象后,需要获取结果做后续处理操作时候,还是需要阻塞某线程进行等待。这样话,同步调用方式就没有多大区别了。而...

    一、作用

    jdk1.8之前的Future模式一个最大的问题是:向线程池提交任务异步执行并获取的Future对象后,需要获取结果做后续处理操作的时候,还是需要阻塞某线程进行等待。这样的话,和同步调用方式就没有多大区别了。而ListenableFuture和CompletableFuture对于这种情况则是提供了很多易用的API。

    如果说按照先后顺序来讲的话,首先是ListenableFuture,这是由Google Guava工具包提供的Future扩展类,随后,JDK在1.8版本中马上也提供了类似这样的类,就是CompletableFuture。

    如果项目使用的jdk版本是1.8及以上,则直接使用CompletableFuture就可以了,下面分别介绍这两种工具的使用:

    二、Google的ListenableFuture

    先来聊聊ListenableFuture,一句话概括ListenableFuture和JDK原生Future最大的区别是前者做到了一个可以监听结果的Future。换个更通俗的讲法,就是它可以监听异步执行的过程,执行完了,自动触发什么操作。除此之外,可以分别针对成功的情况,或者失败的情况做各种后续处理

    package com.mzj.guava.concurrent.future;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.Executors;
    
    import org.junit.Test;
    
    import com.google.common.util.concurrent.FutureCallback;
    import com.google.common.util.concurrent.Futures;
    import com.google.common.util.concurrent.ListenableFuture;
    import com.google.common.util.concurrent.ListeningExecutorService;
    import com.google.common.util.concurrent.MoreExecutors;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ListenableFutureExample {
    
        /**
         * The unit test for ListenableFuture/CompletableFuture. * Created by yiqun01.lin * on 2018/5/3.
         */
        //线程池中线程个数
        private static final int POOL_SIZE = 50;
        //带有回调机制的线程池
        private static final ListeningExecutorService service = MoreExecutors
                .listeningDecorator(Executors.newFixedThreadPool(POOL_SIZE));
    
        private static Logger LOG = LoggerFactory.getLogger(ListenableFutureExample.class);
    
        @Test
        public void testListenableFuture() {
            final List<String> value = Collections
                    .synchronizedList(new ArrayList<String>());
            try {
                List<ListenableFuture<String>> futures = new ArrayList<ListenableFuture<String>>();
                // 将实现了callable的任务放入到线程池中,得到一个带有回调机制的ListenableFuture实例,
                // 通过Futures.addCallback方法对得到的ListenableFuture实例进行监听,一旦得到结果就进入到onSuccess方法中,
                // 在onSuccess方法中将查询的结果存入到集合中
                for (int i = 0; i < 1; i++) {
                    final int index = i;
                    if (i == 9) {
                        Thread.sleep(500 * i);
                    }
                    ListenableFuture<String> sfuture = service
                            .submit(new Callable<String>() {
                                @Override
                                public String call() throws Exception {
                                    long time = System.currentTimeMillis();
                                    LOG.info("Finishing sleeping task{}: {}", index, time);
                                    return String.valueOf(time);
                                }
                            });
                    sfuture.addListener(new Runnable() {
                        @Override
                        public void run() {
                            LOG.info("Listener be triggered for task{}.", index);
                        }
                    }, service);
    
                    Futures.addCallback(sfuture, new FutureCallback<String>() {
                        public void onSuccess(String result) {
                            LOG.info("Add result value into value list {}.", result);
                            value.add(result);
                        }
    
                        public void onFailure(Throwable t) {
                            LOG.info("Add result value into value list error.", t);
                            throw new RuntimeException(t);
                        }
                    });
                    // 将每一次查询得到的ListenableFuture放入到集合中
                    futures.add(sfuture);
                }
    
                // 这里将集合中的若干ListenableFuture形成一个新的ListenableFuture
                // 目的是为了异步阻塞,直到所有的ListenableFuture都得到结果才继续当前线程
                // 这里的时间取的是所有任务中用时最长的一个
                ListenableFuture<List<String>> allAsList = Futures.allAsList(futures);
                allAsList.get();
                LOG.info("All sub-task are finished.");
            } catch (Exception ignored) {
            }
        }
    
    
    }
    

    三、JDK1.8的CompletableFuture

    我们再来看看CompletableFuture的使用,这个是在JDK8中开始引入的,这个在一定程度上与ListenableFuture非常类似。比如说ListenableFuture的listener监听回调,在这个类中,相当于thenRun或者whneComplete操作原语。CompletableFuture提供的API其实有很多,从大的方向上来划分的话,有下面几类:

    public static CompletableFuture<Void>     runAsync(Runnable runnable)  
    public static CompletableFuture<Void>     runAsync(Runnable runnable, Executor executor)  
    public static <U> CompletableFuture<U>  supplyAsync(Supplier<U> supplier)  
    public static <U> CompletableFuture<U>  supplyAsync(Supplier<U> supplier, Executor executor)

    注意到这里,runAsync是不带类型返回的,Void,而supplyAsync API需要传入类型的,整型,字符串或者其它,然后是否需要在额外的线程池里执行这些Async操作,如果没有指定,会默认在ForkJoinPool提供的common pool里跑

    CompletableFuture在设计上采用JDK1.8原生的函数式编程风格。

    package com.mzj.guava.concurrent.future;
    
    import java.util.concurrent.CompletableFuture;
    
    import org.junit.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class CompletableFutureExample {
    
            private static Logger LOG = LoggerFactory.getLogger(CompletableFutureExample.class);
    
            @Test
            public void testCompletableFuture() throws Exception {
                // case1: supplyAsync
                CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                    LOG.info("Run supplyAsync.");
                    return "Return result of Supply Async";
                });
    
                // case2: thenRun,与supplyAsync同线程
                future.thenRun(new Runnable() {
    
                    @Override
                    public void run() {
                        LOG.info("Run action.");
                    }
                });
    
                // case2: thenRunAsync,另启动线程执行
                future.thenRunAsync(new Runnable() {
    
                    @Override
                    public void run() {
                        LOG.info("Run async action.");
                    }
                });
    
                // 主动触发Complete结束方法
                // future.complete("Manual complete value.");
                future.whenComplete((v, e) -> {
                    LOG.info("WhenComplete value: " + v);
                    LOG.info("WhenComplete exception: " + e);
                });
                CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
                    LOG.info("Return result of Run Async.");
                });
    
                CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
                    return "hello";
                });
                CompletableFuture<String> future4 = CompletableFuture.supplyAsync(() -> {
                    return "world";
                });
                CompletableFuture<String> f = future3.thenCombine(future4,
                        (x, y) -> x + "-" + y);
                LOG.info(f.get());
            }
    }
    

    四、完整工程示例

    https://github.com/mazhongjia/googleguava/tree/master/src/main/java/com/mzj/guava/concurrent/future

    五、扩展阅读

    jdk的CompletableFuture接口较多,可以阅读如下文章加强理解

    https://www.jianshu.com/p/6bac52527ca4

    https://www.jianshu.com/p/b3c4dd85901e

    ——E:\01.study\10.java基础\java8\01.CompletableFuture

     

     

    展开全文
  • XMLHTML都来自于SGML,它们都含有标记,有着相似的语法,HTMLXML的最大区别在于:HTML是一个定型的标记语言,它用固有的标记来描述,显示网页内容。比如表示首行标题,有固定的尺寸。相对的,XML则没有固定的...
  • 3.7 是否可以安全地认为,一旦&&||左边表达式已经决定了整个表达式的结果,则右边表达式不会被求值? 3.8 为什么表达式printf("%d%d",f1(),f2());先调用了f2?我觉得逗号表达式应该确保从左到右求值顺序。...
  • 3.7 是否可以安全地认为,一旦&&||左边表达式已经决定了整个表达式的结果,则右边表达式不会被求值? 3.8 为什么表达式printf("%d%d",f1(),f2());先调用了f2?我觉得逗号表达式应该确保从左到右求值顺序。...
  • ='\n')代码…… 3.7 是否可以安全地认为,一旦&&||左边表达式已经决定了整个表达式的结果,则右边表达式不会被求值? 3.8 为什么表达式printf("%d%d",f1(),f2());先调用了f2?我觉得逗号表达式应该确保从...
  • 进程线程之间最大的区别是进程有着自己地址空间,而线程共享创建它们进程地址空间。在将C++任务映射为操作系统能够理解执行单元时,结果证明线程更易于编程,其主要原因是线程共享相同地址空间,使得...
  • 《你必须知道495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    3.7 是否可以安全地认为,一旦&&||左边表达式已经决定了整个表达式的结果,则右边表达式不会被求值? 36  3.8 为什么表达式printf("%d %d", f1(), f2()); 先调用了f2?我觉得逗号表达式应该确保从左到右...
  • 3.7 是否可以安全地认为,一旦&&||左边表达式已经决定了整个表达式的结果,则右边表达式不会被求值? 36  3.8 为什么表达式printf(%d %d, f1(), f2()); 先调用了f2?我觉得逗号表达式应该确保从左到右求...
  • 第6章 异步、多线程、任务和并行 / 177 建议71:区分异步和多线程应用场景 / 177 建议72:在线程同步中使用信号量 / 180 建议73:避免锁定不恰当同步对象 / 184 建议74:警惕线程IsBackground / 188 建议...
  • excel使用

    2012-11-25 17:06:01
    如果想恢复公式计算结果的显示,就再设置“窗口选项”栏下的“公式”项失效即可。图2(8) 利用Ctrl+*选取文本如果一个工作表中有很多数据表格时,可以通过选定表格中某个单元格,然后按下Ctrl+*键可选定整个表格...
  • 并说出SessionBeanEntityBean的区别,StatefulBeanStatelessBean的区别。 EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。 SessionBean在J2EE应用程序中被用来完成...
  • 其中使用Struts作为系统整体基础架构,负责MVC分离,在Struts框架模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring管理,管理StrutsHibernate。 WebStorage HTML新增本地存储解决...
  • StringBuilder 类提供...这些操作修改了 str 对象值,而没有创建新对象,这就是 StringBuilder String 最大的区别。 运行结果:  任务 功能:将一个由英文字母组成字符串转换成指定格式---从右边

    StringBuilder 类提供了很多方法来操作字符串:

    例如:在下面的示例代码中,创建了 StringBuilder 对象,用来存储字符串,并对其做了追加和插入操作。这些操作修改了 str 对象的值,而没有创建新的对象,这就是 StringBuilder 和 String 最大的区别。

    运行结果: 

    任务

    功能:将一个由英文字母组成的字符串转换成指定格式---从右边开始每三个字母用逗号分隔的形式。

    请在编辑器中的第 4、10 行将代码填写完整

    运行效果: j,aew,kjl,dfx,mop,zdm

    ?不会了怎么办

    参考代码:

    展开全文
  • 而我们要做的,就是读懂报告中各种专业术语,并分辨出哪些因素影响了网页加载性能。 术语 <h3>FP、FCP、FMP与LCP 从前面评测报告中,我们会看到FP、FCP、FMP与LCP这几个字母很接近术语&#...
  • 主要目的是用来信息展示传播。这个时候开发一个网页也很容易,主要就是通过 JSP、PHP 等技术写一些动态模板,然后通过 Web Server 将模板解析成一个个 HTML 文件,浏览器只负责渲染这些 ...
  • 4.3.2 errorexception的区别,CheckedException,RuntimeException的区别。 4.3.3 请列出5个运行时异常。 4.3.4 在自己代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加载?为什么。 ...
  • 你必须知道495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    不同编译器给出不同的结果, 有为 3, 有为4, 哪个是正确? . . . . . . . . . . . . . . . . . . . . . 14 3.4 这是个巧妙表达式: a ˆ= b ˆ= a ˆ= b 它不需要临时变量就可 以交换a b 值。. . . . . ....
  • 瀑布模型的最大优点是将软件开发的各个阶段划分得十分清晰。(×) 3. 结构化方法的工作模型是使用螺旋模型进行开发。(×) 4. 结构化方法JSP方法都不适合于大型软件的开发。(√) 5. 原型化开发方法包括生成原型...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    类图对象图的区别 包 包 一种分组机制,把各种各样模型元素通过内在语义连在一起成为一个整体就叫做包 包关系 包--软件比赛作品 架构图--包图变形 任务4 UML动态建模机制 对象之间交互 状态图...
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    18.2 在 C #代码中调用 C++ VB 编写组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...
  • C#微软培训资料

    2014-01-22 14:10:17
    18.2 在 C #代码中调用 C++ VB 编写组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...
  • 即使他在这一方面得象一个行业发言人一样好,但如果他缺乏对供给、需求以及市场功能研究有关知识,就不可能成为一个称职公司经理或者企业代理人。事实上,在进行管理学专业培养时候,为了研究利润及奖惩等...
  • 讲座目的就是在同学们中间普及 Linux 基础知识,为今后我们更加接近了解 Linux 一 个好开端。 第一讲 Linux基础 在这一讲中,我们主要是了解一下 Linux 概况,以及对 Linux 有一个初步感性认识。 ...
  • 两者最大的区别在于Storm会保证消息得到处理。这些系统中有拥有内建数据存储层,这是Storm所没有,如果需要持久化,可以使用一个类似于Cassandra或Riak这样外部数据库。 入门最佳途径是阅读GitHub上官方...
  •  本书最大的特点是侧重于理论讲述实战演练,尤其是对理论剖析有一定深度,并通过大量完整案例来论证这些理论。DBA开发人员特点不同,对于开发人员来说,从某种角度上,强调创造力决定高度。但是DBA要求...
  •  在这本书里,你将会学到笔者在性能优化方面一些思路思考,一些故障处理方法原则,这些东西是笔者在实践中长期积累心得体会,在笔者看来,掌握处理问题方法分析问题思路在日常工作中显得更为重要,...

空空如也

空空如也

1 2 3 4
收藏数 64
精华内容 25
关键字:

做任务和做结果的最大区别