Runnable 是一个接口,里面只声明了一个方法run();返回值为void所以无法拿到执行完的结果。只能通过共享变量或者线程通信来搞定。
Future就是对具体的Runable或者Callable任务的执行结果进行取消,查询是否完成,获取结果。
FutureTask实现了RunnableFuture接口,RunableFuture接口继承了Runable和Future接口,所以他既可以被线程执行,也可以作为Future得到Callable的返回值。
CompletableFutures是java8中新增加的一个类,主要用来处理异步。CompletableFuture不但可以调用get()方法获取执行结果,也可以使用回调函数来得到处理结果CompletableFuture可以通过completeExceptionally 函数来发出异常通知,同时我们也可以显示声明异常处理。CompletableFuture还有许多方法,来满足不同的需求场景,具体的方法 还需要使用到的时候在来进行具体分析。

在两个线程里并行执行任务A和任务B,只要有一个任务完成了,就执行任务C。代码如下:

  1. import java.time.LocalTime;
  2. import java.util.Random;
  3. import java.util.concurrent.CompletableFuture;
  4. import java.util.concurrent.ExecutionException;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. import java.util.concurrent.Future;
  8. import java.util.concurrent.TimeUnit;
  9. import java.util.concurrent.TimeoutException;
  10. public class LearnCompleteFuture {
  11. private static Random random = new Random();
  12. public static void main(String[] args) throws InterruptedException, ExecutionException {
  13. useFuture();
  14. TimeUnit.SECONDS.sleep(10);
  15. System.out.println();
  16. useCompletableFuture();
  17. }
  18. private static void useFuture() throws InterruptedException, ExecutionException {
  19. System.out.println("Future");
  20. ExecutorService exector = Executors.newFixedThreadPool(3);
  21. Future<Void> futureA = exector.submit(() -> work("A1"));
  22. Future<Void> futureB = exector.submit(() -> work("B1"));
  23. while (true) {
  24. try {
  25. futureA.get(1, TimeUnit.SECONDS);
  26. break;
  27. } catch (TimeoutException e) {
  28. }
  29. try {
  30. futureB.get(1, TimeUnit.SECONDS);
  31. break;
  32. } catch (TimeoutException e) {
  33. }
  34. }
  35. exector.submit(() -> work("C1")).get();
  36. exector.shutdown();
  37. }
  38. private static void useCompletableFuture() throws InterruptedException, ExecutionException {
  39. System.out.println("CompletableFuture");
  40. CompletableFuture<Void> futureA = CompletableFuture.runAsync(() -> work("A2"));
  41. CompletableFuture<Void> futureB = CompletableFuture.runAsync(() -> work("B2"));
  42. futureA.runAfterEither(futureB, () -> work("C2")).get();
  43. }
  44. public static Void work(String name) {
  45. System.out.println(name + " starts at " + LocalTime.now());
  46. try {
  47. TimeUnit.SECONDS.sleep(random.nextInt(10));
  48. } catch (InterruptedException e) {
  49. }
  50. System.out.println(name + " ends at " + LocalTime.now());
  51. return null;
  52. }
  53. }

两种方法useFuture和useCompletableFuture相比:

首先,方法2 比 方法1 的代码简单。在方法1里,既要自己照顾线程池的创建和销毁,还要负责对任务A和任务B的监控。而方法2,只需要用CompletableFuture的runAfterEither就完成了任务A、任务B和任务C之间的依赖关系的定义。

在方法2,甚至用一行代码就能完成:

  1. CompletableFuture.runAsync(() -> work("A2")).runAfterEither(CompletableFuture.runAsync(() -> work("B2")), () -> work("C2")).get();

其次,方法2 比 方法1 高效。

方法1的主线程,要通过while(true)的方式不断地轮询任务A和任务B的运行状况,浪费CPU资源,而方法2的主线程只需要在最后的get()上静静地等待任务C的完成。

http://blog.csdn.net/zjysource/article/details/54409772

Java多线程相关的常用接口的更多相关文章

  1. Java多线程相关的

    很多小伙伴在学习Java的时候,总是感觉Java多线程在实际的业务中很少使用,以至于不会花太多的时间去学习,技术债不断累积!等到了一定程度的时候对于与Java多线程相关的东西就很难理解,今天需要探讨的 ...

  2. Java多线程相关面试题及答案-整理

    1.什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任务提速.比如,如果一个线程完成 ...

  3. Java[3] Java多线程相关资料

    Java多线程: http://www.uml.org.cn/j2ee/201509093.asp

  4. Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier

    Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...

  5. 2018/1/15 JAVA多线程相关

    本文不说synchronized相关,它就是JAVA的一个保留关键字,jdk自己实现了它,但说真的,可应用场景真的少,相比lock接口,它还是被淘汰好吧; 首先,说说lock接口,lock接口是一个工 ...

  6. java多线程相关代码

    1.创建线程的三种方式 使用Thread package com.wpbxx.test; //1.自定义一个类,继承java.lang包下的Thread类 class MyThread extends ...

  7. Java多线程之实现Runnable接口

    package org.study2.javabase.ThreadsDemo.runnable; /** * @Auther:GongXingRui * @Date:2018/9/18 * @Des ...

  8. Java : JPA相关以及常用注解

    SpringDataJPA自定义的查询方法 定义规范       And 并且 Or 或     Is,Equals 等于 Between 两者之间 LessThan 小于 LessThanEqual ...

  9. Java多线程:实现API接口创建线程方式详解

    先看例子: /**实现Runnable接口创建线程步骤: * 1.创建一个实现Runnable接口的类 * 2.重写Runnable类中抽象的run()方法 * 3.创建实现类的对象 * 4.声明Th ...

随机推荐

  1. 在WEB项目中调用QQ通讯组件打开QQ聊天界面

    在很多WEB项目中,需要提供在线服务的功能,加上自己的联系方式,例如:QQ,不用添加QQ好友也可以交谈,那这到底是怎么实现的呢? 对于这个功能,需要提到一个组件,即“QQ通讯组件”.QQ通讯组件是一种 ...

  2. linux shell学习笔记二---自定义函数(定义、返回值、变量作用域)介绍

    linux shell 可以用户定义函数,然后在shell脚本中可以随便调用.下面说说它的定义方法,以及调用需要注意那些事项. 一.定义shell函数(define function) 语法: [ f ...

  3. LINUX-初始化一个文件系统

    mkfs /dev/hda1 在hda1分区创建一个文件系统 mke2fs /dev/hda1 在hda1分区创建一个linux ext2的文件系统 mke2fs -j /dev/hda1 在hda1 ...

  4. HDU - 6446 Tree and Permutation

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6446 本题是一个树上的问题——DFS. 一棵N个结点的树,其结点为1~N.树具有N-1条边,每一条边具有 ...

  5. [bzoj2431][HAOI2009][逆序对数列] (dp计数)

    Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆 ...

  6. RequestMapping_Ant 路径

    [使用@RequestMapping映射请求] [Ant风格资源地址支持3种匹配符] (1)? :匹配文件名中的一个字符. (2) * :匹配文件名中的任意字符. (3) ** :**匹配多层路径. ...

  7. Android layer-list(3)

     Android layer-list(3) 在附录文章3.4的基础上,就Android layer-list再写一个较为复杂的应用. 先写布局文件,该布局涉及到LinearLayoutCompa ...

  8. Mongodb慢查询笔记 (Mongodb slow query log)

    -- =========================== -- mongodb slow query log -- =========================== Reference: h ...

  9. JS动态添加div,然后在div中添加元素

    需求: 组织部中有个这样的需求,根据年份动态显示该年份下的定性指标! 我的做法: 先是放一个空的div,让后根据指标的数据,动态的往div中添加元素. 代码: 空的div,存放定性指标 <div ...

  10. [codeVS1404] 字符串匹配

    时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master         题目描述 Description 给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度. ...