一. 线程基础知识
1.Java多线程相关概念
(1) 1把锁synchronized
(2) 2个并
- 并发(concurrent)
是在同一实体上的多个事件
是在一台处理器上"同时"处理多个任务
同一时刻,其实只有一个事件在发生
- 并行(parallel)
是在不同实体上的多个事件
是在多台处理器上同时处理多个任务
- 并发vs并行
(3) 3个程
- 进程:在系统中运行的一个应用程序就是一个进程,每一个进程都有它自己的内存空间和系统资源.
- 线程:也称为`轻量级进程`,在同一个进程内会有1个或多个线程,是大多数操作系统进行时序调度的基本单元.
- 管程: Monitor(监视器),也就是我们平时所说的锁
2. 用户线程和守护线程
(1)Java线程分为用户线程和守护线程
- 一般情况下,`默认都是用户线程`
- 用户线程:是系统的工作线程,它会完成这个程序需要完成的业务操作
- 守护线程
- 是一种特殊的线程`为其他线程服务的`,在后台默默完成一些系统性的服务,比如垃圾回收线程就是最典型的例子
- 守护线程作为一个服务线程,没有服务对象就没有必要继续运行了.
(2) 线程的daemon属性
- true表示是守护线程
- false表示是用户线程
(3)小总结
- 如果用户线程全部结束意味着程序需要完成的业务操作已经结束了,守护线程随着JVM一同结束工作
- setDaemon(true)方法必须在start()之前设置,否则报IllegalThreadStateException异常
二 CompletableFuture
1. Future接口能干什么
Future接口可以为主线程开一个分支任务,专门为主线程处理耗时和费力的复杂任务.它提供了一种异步并行计算的功能
- 目的:异步多线程任务执行且返回有结果,三个特点:多线程/有返回/异步任务
2. Future接口常用实现类FutureTask异步任务
- 优点:future+线程池异步多线程配合,能显著提高程序的执行效率
- 缺点:
- get()阻塞:一旦调用get()方法求结果,如果没有计算完成容易导致程序阻塞.
- isDone()轮询:轮询的方式会耗费无谓的CPU资源,而且也不见得能及时地得到计算结果;
- 如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞
- Future对于结果的获取不是很友好,只能通过阻塞或轮询的方式得到任务的结果.
- 想完成一些复杂的任务
- 对于简单的业务场景使用Future完全OK
- 回调通知
- 应对Future的完成时间,完成了可以告诉我,也就是我们的回调通知
- 通过轮询的方式去判断任务是否完成这样非常占CPU并且代码也不优雅
- 创建异步任务:Future+线程池配合
- 多个任务前后依赖可以组合处理
- 想将多个异步任务的计算结果组合起来,后一个异步任务的计算结果需要前一个异步任务的值
- 将两个或多个异步计算合成一个一部计算,这几个异步计算互相独立,同时后面这个又依赖前一个处理的结果.
- 对计算速度选最快:当Future集合中某个任务最快结束时,返回结果,返回第一名处理
- Future能干的,CompletableFuture都能干
3.CompletableFuture对Future的改进
- CompletableFuture为什么出现
阻塞的方式和异步编程的设计理念相违背,而轮询的方式会耗费无谓的CPU资源
JDK8设计出CompletableFuture,提供了一套观察者模式类似的机制,可以让任务执行完成后通知坚挺的一方. - CompletableFuture和CompletionStage源码分别介绍
接口CompletionStage- CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另一个阶段,类似于Linux系统的管道分隔符传参数
类CompletableFuture - CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture的方法
- 他可能代表一个明确完成的Future,也有可能代表一个完成阶段,它支持在计算完成以后触发一些函数或执行某些动作
- 它实现了Future和CompletionStage接口
- CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另一个阶段,类似于Linux系统的管道分隔符传参数
- 核心的四个静态方法,来创建一个异步任务
- runAsync无返回值
- supplyAsync有返回值
- Executor executor参数说明:如果指定线程池,则使用我们自定义的或者特别指定的线程池执行异步代码
- CompletableFuture的优点
- 异步任务结束后,会自动回调某个对象的方法
- 主线程设置好回调后,不再关心异步任务的执行,异步任务之间可以顺序执行
- 异步任务出错时,会自动回调某个对象的方法
4.从电商网站的比价需求说
- 函数式编程已经主流
Lambda表达式+Stream流式调用+Chain链式调用+Java8函数式编程
- Runnable
- Function
- Consumer
- Supplier
先说说join和get对比
5. CompletableFuture常用方法
- 获得结果和触发计算
- 获取结果
- 对计算结果进行处理
- 对计算结果进行消费
- 对计算速度进行选用
- 对计算结果进行合并
三、说说Java“锁”事
1. 从轻松的乐观锁和悲观锁开讲
- 悲观锁:认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。
- 适合写操作多的场景,先加锁可以保证写操作时数据正确
- 显式的锁定之后再操作同步资源 (狼性锁)
- 乐观锁:认为自己在使用数据时`不会有别的线程修改数据或资源`,所以不会添加锁
- 适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升
- 乐观锁则直接去操作同步资源,是一种无锁算法 (佛系锁)
synchronized关键字和Lock的实现类都是悲观锁
乐观锁最常用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现
本文介绍了Java多线程的基础知识,包括并发与并行的区别,用户线程与守护线程的概念,以及线程的daemon属性。接着讨论了Future接口在异步计算中的作用,但其get()方法可能导致阻塞,而CompletableFuture作为Future的增强版,提供了非阻塞和函数式编程的能力。最后,文章探讨了乐观锁与悲观锁的策略,指出CAS算法在乐观锁中的应用。
3794

被折叠的 条评论
为什么被折叠?



