总述

  • 线程和任务对应,程序员书写任务,线程负责执行任务
  • 站在任务的角度,考虑任务的执行顺序
  • 站在线程的角度,考虑线程的同步或异步

注意

  • CompletableFuture使用的是ForkJoinPool线程池中的线程
  • ForkJoinPool 线程池中的线程作为主线程的守护线程;主线程一旦停止,守护线程立马停止

介绍

CompletableFuture

  • CompletableFuture.SupplyAsync(任务1).thenAsync(任务2)
  • 括号中写的都是任务;其实代码中写的是静态的东西-任务和线程调度规则;线程是动态的
  • 任务串行、线程异步;线程1执行任务1,线程2执行任务2;任务2需要获取任务1的返回值;线程2执行任务2拿到返回值之前,线程1与线程2可以异步

ForkJoinPool

  • CompletableFuture使用的是ForkJoinPool.commonPool线程池中的线程
  • ForkJoinPool.commonPool线程池中的线程作为主线程的守护线程;主线程一旦停止,守护线程立马停止
  • ForkJoinPool.commonPool线程池时整个spring上下文共享的线程池

函数式接口

函数式接口

详解

  • xxxAsync方法:从线程池中取线程执行任务
  • 不带xxxAsync方法:使用以前的线程或main线程执行任务
  • xxxEitherxxx方法:要么调用此方法的CF完成,要么此方法入参CF完成,执行此方法中的任务

构造方法

方法 简介
new CompletableFuture() 返回值为Void
new CompletableFuture(result) 返回值为给定result
CompletableFuture.completedFuture(null) 等价于new CompletableFuture()
CompletableFuture.completedFuture(result) 等价于new CompletableFuture(result)
CompletableFuture.supplyAsync(Supplier<U> supplier) 从线程池中取线程执行任务
CompletableFuture.runAsync(Runnable runnable) 从线程池中取线程执行任务

常用方法

方法 简介
supplyAsync(Supplier<U> supplier) 从线程池中取线程执行任务
runAsync(Runnable runnable) 从线程池中取线程执行任务
thenApply(Function<? super T,? extends U> fn) 使用以前的线程或主线程执行任务
thenApplyAsync(Function<? super T,? extends U> fn) 从线程池中取线程执行任务
thenRun(Runnable action) 使用以前的线程或主线程执行任务
thenRunAsync(Runnable action) 从线程池中取线程执行任务
thenAccept(Consumer<? super T> action) 使用以前的线程或主线程执行任务
thenAcceptAsync(Consumer<? super T> action) 从线程池中取线程执行任务
allOf(CompletableFuture<?>... cfs) 其中任务全部并发&&全部执行完成进入下一步
anyOf(CompletableFuture<?>... cfs) 其中任务全部并发&&任意一个执行完成进入下一步
get() 等待获取返回结果,会阻塞main线程,外部进行异常处理
exceptionally(Function<Throwable, ? extends T> fn) 异常处理并给定值,再调用get()会获取这个给定值;不会阻塞main线程

剩余方法

方法 简介
boolean isDone() 执行完成返回true;完成-正常完成,异常完成,通过取消执行完成
boolean isCancelled() 如果CF在正常完成前被取消,返回true
boolean isCompletedExceptionally() 如果CF异常完成,返回true
boolean cancel(boolean mayInterruptIfRunning) 如果CF未完成,通过抛出CancellationException完成;相关的CF会通过抛出CompletionException完成;CF被取消正常完成返回true
T join() 阻塞main线程,等待获取CF返回结果;不需要外部进行异常处理unchecked exception
T get() 阻塞main线程,无限等待获取CF返回结果,;外部进行异常处理
T get(long timeout, TimeUnit unit) 阻塞main线程,有限等待获取CF返回结果;外部进行异常处理
T getNow(T valueIfAbsent) 已完成获取返回值,未完成获取给定值
int getNumberOfDependents() 返回正在等待调用此方法的CF完成的CF数量
boolean complete(T value) 如果调用此方法的CF未完成,设置get()方法和相关方法的返回值为给定值;如果CF调用此方法导致CF自己变为完成状态则返回ture,否则返回false
boolean completeExceptionally(Throwable ex) 如果调用此方法的CF未完成,调用get()方法和相关方法将抛出给定异常;如果CF调用此方法导致CF自己变为完成状态则返回ture,否则返回false
void obtrudeValue(T value) 强制重置get()方法和相关方法的返回值
void obtrudeException(Throwable ex) 强制重置get()方法和相关方法抛出的异常
CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) 使用以前的线程或main线程执行此方法;CF完成时调用回调此方法;正常完成T有值,Throwable为null;异常完成T为null,Throwable有值
CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) 从线程池中取线程执行此方法;CF完成时回调此方法;正常完成T有值,Throwable为null;异常完成T为null,Throwable有值
<U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) 使用以前的线程或主线程执行任务;CF完成时回调此方法;正常完成T有值,Throwable为null;异常完成T为null,Throwable有值
<U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn) 从线程池中取线程执行此方法;CF完成时回调此方法;正常完成T有值,Throwable为null;异常完成T为null,Throwable有值
CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action) 当此方法内的CF或外的CF正常执行完成;使用以前的线程或main线程执行此方法中的任务
CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action) 当此方法内的CF或外的CF正常执行完成;使用线程池中的线程执行此方法中的任务
CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action) 当此方法内外的CF都正常执行完成;使用以前的线程或main线程执行此方法中的任务
CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action) 当此方法内外的CF都正常执行完成;使用线程池中的线程执行此方法中的任务
CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action) 当此方法内的CF或外的CF正常执行完成;使用以前的线程或main线程执行此方法中的任务
CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action) 当此方法内的CF或外的CF正常执行完成;使用线程池中的线程执行此方法中的任务
<U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action) 当此方法内外的CF都正常执行完成;使用以前的线程或main线程执行此方法中的任务
<U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action) 当此方法内外的CF都正常执行完成;使用线程池中的线程执行此方法中的任务
<U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn) 当此方法内的CF或外的CF正常执行完成;使用以前的线程或main线程执行此方法中的任务
<U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn) 当此方法内的CF或外的CF正常执行完成;使用线程池中的线程执行此方法中的任务
<U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn) 把外部CF的返回结果作为内部CF的输入,使用以前的线程或main线程执行内部CF中的任务
<U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) 把外部CF的返回结果作为内部CF的输入,使用线程池执行内部CF中的任务
<U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn) 合并内外CF的返回值,使用以前的线程或main线程执行BiFunction中的任务
<U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn) 合并内外CF的返回值,使用线程池执行BiFunction中的任务

使用-并行任务-allOf()

介绍

  • 孙悟空的一天,任务1-打游戏,任务2-搞学习,任务3-吃饭
  • 任务1和任务2之间没有任何关系可以并行,任务3需要等到任务1和任务2都完成之后才能执行
  • 孙悟空分出2个分身(线程),分身1-打游戏,分身2-搞学习,分身3-吃午饭;分身1把游戏打完了,分身2把学习搞完了,分身3才允许吃饭

代码

public class SunWuKong {public static void main(String[] args) {CompletableFuture cf1 = CompletableFuture.runAsync(() -> {try {Thread.currentThread().sleep(5000);} catch (Exception ex) {}SunWuKong sunWuKong1 = new SunWuKong();sunWuKong1.duty1();});CompletableFuture cf2 = CompletableFuture.runAsync(() -> {SunWuKong sunWuKong2 = new SunWuKong();sunWuKong2.duty2();});CompletableFuture all = CompletableFuture.allOf(cf1, cf2).thenRun(() -> {SunWuKong sunWuKong3 = new SunWuKong();sunWuKong3.duty3();});try {// 等待获取返回结果,会阻塞main线程,外部异常处理all.get();} catch (Exception ex) {System.out.println(ex.getMessage());}}private void duty1() {System.out.println("分身:" + Thread.currentThread().getName() + ",打游戏");}private void duty2() {System.out.println("分身:" + Thread.currentThread().getName() + ",搞学习");}private void duty3() {System.out.println("分身:" + Thread.currentThread().getName() + ",吃饭");}
}

使用-并行任务-runAfterBothAsync()

介绍

  • 孙悟空的一天,任务1-打游戏,任务2-搞学习,任务3-吃饭
  • 任务1和任务2之间没有任何关系可以并行,任务3需要等到任务1和任务2都完成之后才能执行
  • 孙悟空分出2个分身(线程),分身1-打游戏,分身2-搞学习,分身3-吃午饭;分身1把游戏打完了,分身2把学习搞完了,分身3才允许吃饭

代码

public class SunWuKong {public static void main(String[] args) {try {CompletableFuture.runAsync(() -> {try {Thread.currentThread().sleep(5000);} catch (Exception ex) {}SunWuKong sunWuKong1 = new SunWuKong();sunWuKong1.duty1();}).runAfterBothAsync(CompletableFuture.runAsync(() -> {SunWuKong sunWuKong2 = new SunWuKong();sunWuKong2.duty2();}), () -> {SunWuKong sunWuKong3 = new SunWuKong();sunWuKong3.duty3();}).get();} catch (Exception ex) {System.out.println(ex.getMessage());}}private void duty1() {System.out.println("分身:" + Thread.currentThread().getName() + ",打游戏");}private void duty2() {System.out.println("分身:" + Thread.currentThread().getName() + ",搞学习");}private void duty3() {System.out.println("分身:" + Thread.currentThread().getName() + ",吃饭");}
}

使用-并行任务-anyOf()

介绍

  • 孙悟空现口渴,任务1-找果汁喝,任务2-找矿泉水喝,任务3-搞学习
  • 任务1或者任务2执行完毕孙悟空都能解渴;任务1或者任务2执行完毕后,任务3才能执行
  • 孙悟空分出3个分身(线程),分身1-找果汁喝,分身2-找矿泉水喝,分身3-搞学习;分身1找到果汁喝了或者分身2找到矿泉水喝了,分身3才能搞学习

代码

public class SunWuKong {public static void main(String[] args) {CompletableFuture cf1 = CompletableFuture.runAsync(() -> {try {Thread.currentThread().sleep(5000);} catch (Exception ex) {}SunWuKong sunWuKong1 = new SunWuKong();sunWuKong1.duty1();});CompletableFuture cf2 = CompletableFuture.runAsync(() -> {SunWuKong sunWuKong2 = new SunWuKong();sunWuKong2.duty2();});CompletableFuture all = CompletableFuture.anyOf(cf1, cf2).thenRun(() -> {SunWuKong sunWuKong3 = new SunWuKong();sunWuKong3.duty3();});try {// 等待获取返回结果,会阻塞main线程,外部异常处理all.get();} catch (Exception ex) {System.out.println(ex.getMessage());}}private void duty1() {System.out.println("分身:" + Thread.currentThread().getName() + ",找果汁喝");}private void duty2() {System.out.println("分身:" + Thread.currentThread().getName() + ",找矿泉水喝");}private void duty3() {System.out.println("分身:" + Thread.currentThread().getName() + ",搞学习");}
}

使用-并行任务-anyOf()

介绍

  • 孙悟空现口渴,任务1-找果汁喝,任务2-找矿泉水喝,任务3-搞学习
  • 任务1或者任务2执行完毕孙悟空都能解渴;任务1或者任务2执行完毕后,任务3才能执行
  • 孙悟空分出3个分身(线程),分身1-找果汁喝,分身2-找矿泉水喝,分身3-搞学习;分身1找到果汁喝了或者分身2找到矿泉水喝了,分身3才能搞学习

代码

public class SunWuKong {public static void main(String[] args) {try {CompletableFuture.runAsync(() -> {try {Thread.currentThread().sleep(5000);} catch (Exception ex) {}SunWuKong sunWuKong1 = new SunWuKong();sunWuKong1.duty1();}).runAfterEitherAsync(CompletableFuture.runAsync(() -> {SunWuKong sunWuKong2 = new SunWuKong();sunWuKong2.duty2();}), () -> {SunWuKong sunWuKong3 = new SunWuKong();sunWuKong3.duty3();}).get();} catch (Exception ex) {System.out.println(ex.getMessage());}}private void duty1() {System.out.println("分身:" + Thread.currentThread().getName() + ",找果汁喝");}private void duty2() {System.out.println("分身:" + Thread.currentThread().getName() + ",找矿泉水喝");}private void duty3() {System.out.println("分身:" + Thread.currentThread().getName() + ",搞学习");}
}

使用-串行结果-thenApplyAsync()

介绍

  • 孙悟空做蛋炒饭,任务1-炒鸡蛋,任务2-炒饭
  • 任务2需要任务1的执行结果,任务2在不需要任务1的结果之前,任务1和任务2仍然可以并行执行
  • 孙悟空分出2个分身(线程),分身1-炒鸡蛋,分身2-炒饭;分身1-把炒好的鸡蛋放到分身2的炒饭里,分身2-搅拌均匀

代码

public class SunWuKong {public static void main(String[] args) {try {CompletableFuture.supplyAsync(() -> {SunWuKong sunWuKong1 = new SunWuKong();return sunWuKong1.duty1();}).thenAcceptAsync((o) -> {SunWuKong sunWuKong2 = new SunWuKong();String str = sunWuKong2.duty2();System.out.println("把" + o + "放到" + str);}).get();} catch (Exception ex) {System.out.println(ex.getMessage());}}private String duty1() {System.out.println("分身:" + Thread.currentThread().getName() + ",炒鸡蛋");return "炒鸡蛋";}private String duty2() {System.out.println("分身:" + Thread.currentThread().getName() + ",炒饭");return "炒饭";}
}

使用-串行任务-thenApply()

介绍

  • 孙悟空参加铁人三项,必须是同1个人完成“跑步”,“骑单车”,“游泳”
  • 孙悟空分出1个分身(线程),分身先跑步,再骑单车,最后游泳
  • 需要先执行第1个任务再执行第2个任务,直接单线程,一个个任务执行

代码

public class SunWuKong {public static void main(String[] args) {try {CompletableFuture.supplyAsync(() -> {SunWuKong sunWuKong1 = new SunWuKong();return sunWuKong1.duty1();}).thenApply((o) -> {System.out.println("完成" + o);SunWuKong sunWuKong2 = new SunWuKong();return sunWuKong2.duty2();}).thenApply((o) -> {System.out.println("完成" + o);SunWuKong sunWuKong3 = new SunWuKong();return sunWuKong3.duty3();}).get();} catch (Exception ex) {System.out.println(ex.getMessage());}}private String duty1() {try {Thread.currentThread().sleep(5000);} catch (Exception ex) {}System.out.println("分身:" + Thread.currentThread().getName() + ",跑步");return "跑步";}private String duty2() {System.out.println("分身:" + Thread.currentThread().getName() + ",骑单车");return "骑单车";}private String duty3() {System.out.println("分身:" + Thread.currentThread().getName() + ",游泳");return "游泳";}
}

使用-join()-替代allOf

介绍

  • allOf():没有返回值;任务执行顺序-并行
  • join():阻塞main线程直到CF执行完成

代码

allOf()

public static void main(String[] args) {CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "xcrj1");CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> "xcrj2");CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> "xcrj3");CompletableFuture<Void> allCF = CompletableFuture.allOf(cf1, cf2, cf3);System.out.println("no result");
}

join()

public static void main(String[] args) {CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "xcrj1");CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> "xcrj2");CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> "xcrj3");// 并行流String result = Stream.of(cf1,cf2,cf3).parallel().map(CompletableFuture::join).collect(Collectors.joining(","));System.out.println("result:"+result);
}

Java多线程/Java8多线程相关推荐

  1. java8多线程运行程序_线程,代码和数据–多线程Java程序实际运行的方式

    java8多线程运行程序 有些事情是您在学术或培训班上没有学到的,经过几年的工作经验后才逐渐了解,然后才意识到,这是非常基本的事情,我为什么错过了这么多年. 了解多线程Java程序的执行方式就是其中之 ...

  2. JAVA并发之多线程基础(2)

    除了我们经常用的synchronized关键字(结合Object的wait()和notify()使用)之外,还有对应的上篇文章讲到的方法JAVA并发之多线程基础(1)之外,我们日常中使用到最多的也就是 ...

  3. Java基础、多线程、JVM、集合八股文自述(持续更新)

    Java基础.多线程.JVM.集合八股文自述 一.Java基础 1.1 object类有哪些方法? getClass().hashCode().equals().clone().toString(). ...

  4. Java中的多线程编程(超详细总结)

    文章目录 Java中的多线程编程(超详细总结) 一.线程与多线程的概念 二.线程与进程之间的关系 三.一个线程的生命周期 四.多线程的目的和意义 五.线程的实现的方式 Java中的多线程编程(超详细总 ...

  5. Java回顾之多线程

    在这篇文章里,我们关注多线程.多线程是一个复杂的话题,包含了很多内容,这篇文章主要关注线程的基本属性.如何创建线程.线程的状态切换以及线程通信,我们把线程同步的话题留到下一篇文章中. 线程是操作系统运 ...

  6. Java基础之多线程详细分析

    在了解多线程之前,先来了解一下进程与线程之间的关系. 进程和线程: 进程是指在系统中正在执行的一个程序,每个进程之间是独立的. 线程是进程的一个基本执行单元.一个进程要想执行任务,必须得有线程(每1个 ...

  7. java.text.SimpleDateFormat多线程下的问题

    1. 今天在做性能压测的时候发现java.text.SimpleDateFormat多线程下的错误 2. 先贴出两段错误大家看一下: Exception in thread "pool-1- ...

  8. java面试题 多线程_Java面试常见关于多线程的面试题

    多线程是Java技术中常用而且相对比较难易理解的一个知识点.而且多线程也是企业实际应用中必备的技术,因此在面试的过程中,面试者经常被问到关于多线程的问题,遇到这些问题大家应该怎么办呢?赶紧恶补一下Ja ...

  9. JAVA并发之多线程基础(5)

    上面介绍了并发编程中的栅栏等JAVA并发之多线程基础(4) .通过唯一的一个终点线来帮助确定线程是多晚开始执行下一次操作. LockSupport 提供了一个比较底层的线程挂起操作.有点类似于susp ...

最新文章

  1. 每天一点小知识004--关于获取物体名字
  2. Scala 语言之模式匹配(6)
  3. delphi 调用dll 整形返回值_VS2015 编写C++ DLL库及C++、 C#、python 调用
  4. 2018-2019-2 20175224 实验五《网络编程与安全》实验报告
  5. 对layoutInflater的理解
  6. [html] HTML为什么要语义化?语义化有什么好处?
  7. Android缓存学习入门
  8. flask框架_Flask框架的入门:Hello world
  9. Flutter开发 Android Studio 安装第三方模拟器—网易MuMu
  10. win10便签常驻桌面_Win10用户的印象笔记便签深度体验 | 大使专栏
  11. 2017济南北大青鸟accp和学士后课程的真实情况
  12. 萧条下的养殖业成就兽药电子商务新时代
  13. 计算机存储单位字节(Byte)以及单位之间的转换
  14. 复旦大学电子信息专业考研上岸经验分享
  15. 用html制作一个影厅位置图,screenx影厅是什么
  16. 蓝牙BLE方案|智能穿戴市场持续火热,伦茨科技推出智能手表方案
  17. java 实现中文转化为拼音代码 汉字转化为拼音源码分享
  18. 取消小米笔记本插入耳机后弹框
  19. 多测师肖sir_高级讲师_第2个月第35讲解monkey
  20. 重磅!鼎捷软件参与编写制定的机械行业团体标准正式发布

热门文章

  1. 《绿皮书》中的经典台词
  2. 数据分析师兴起并繁荣背后的原因
  3. Dubbo-04 20190317
  4. python+Django搭建web服务器
  5. win10在此计算机上找不到系统映像,图文教你win10系统使用DISM修复找不到源的问题....
  6. 【C++】Clang-Format:代码自动格式化(看这一篇就够了)
  7. CentOS 6.3安装配置LAMP服务器(Linux+Apache+MySQL+PHP5)
  8. golang 使用 gomobile进行 Android 开发
  9. OSChina 周五乱弹 ——如何请假回家追妹子
  10. 播放器上音频断续问题的原因