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. Calendar的用法

    DAY_OF_MONTH的主要作用是cal.get(DAY_OF_MONTH),用来获得这一天在是这个月的第多少天 Calendar.DAY_OF_YEAR的主要作用是cal.get(DAY_OF_Y ...

  2. python的webservice请求

    1.pip install client 2.pip install suds-jurko #coding=utf-8from suds.client import Clientimport time ...

  3. scp 上传文件自动录入密码

    --- 服务器IP地址 des_host=serverIp 服务器存储路径(文件上传后存储指定目录下) des_direc=/home/lk/ 服务器用户密码 des_pass=root_passwo ...

  4. xmpp之配置Xcode(1)

    介绍 ios上的XMPPFramework你能够在Xcode/iPhoneXMPP 目录找到,它只是实现了XMPP的一小部分功能. 下面主要介绍在开发XMPPFramework ios应用之前的配置工 ...

  5. videojs

    <link href="http://vjs.zencdn.net/5.5.3/video-js.css" rel="stylesheet"> &l ...

  6. c/c++编程排坑(1)-- 数据类型的“安静”转换

    这里主要介绍ANSI C的特性:当执行算术运算时,操作数的类型如果不同,就会发生转换.数据类型一般朝着精度更高.长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则 ...

  7. 洛谷——P1775 古代人的难题_NOI导刊2010提高(02)&& P1936 水晶灯火灵(斐波那契数列)

    P1775 古代人的难题_NOI导刊2010提高(02) P1936 水晶灯火灵 斐波那契数列 1.x,y∈[1…k],且x,y,k∈Z 2.(x^2-xy-y^2)^2=1 给你一个整数k,求一组满 ...

  8. list tuple dict (列表,元祖,字典间的相互转换)

    #-*- coding:UTF-8 -*- #author:RXS002 #1.字典 dict = {'name':'Zara','age':7,'class':'First'} #字典转换为字符串, ...

  9. linux动态库加载路径修改

    1.在 /etc/ld.so.conf 文件中添加搜索路径,重启或者 ldconfig 生效: 2.在 /etc/ld.so.conf.d 目录下添加 *.conf 文件,其中可以添加搜索路径,重启获 ...

  10. FJoi2017 1月21日模拟赛 comparison(平衡树+thita重构)

    题目大意: 经黄学长指出,此题原题出自2014湖北省队互测 没有人的算术 规定集合由二元组(A,B)构成,A.B同时也是两个这样的集合,即A.B本身也是二元组 规定二元组S为严格最小集合,S=(S,S ...