多线程进阶=>高并发JUC学习笔记

多线程进阶=>高并发JUC学习笔记

  • 一、什么是JUC?
  • 二、线程与进程
    • ①基础
    • ②线程状态State
    • ③并发与并行
    • ④wait与sleep区别
  • 三、Lock锁
    • ①传统Synchronized方法
    • ②Lock锁
    • ③Synchronized与Lock的区别
    • ④各种锁
      • 1.(非)公平锁
      • 2.可重入锁(递归锁)
        • (1)Synchronized版本
        • (2)Lock版
      • 3.死锁
      • 4.自旋锁[自定义锁]
      • 5.死锁排查
  • 四、生产者和消费者问题
    • 1.Synchronized版本
    • 2.Lock版
  • 五、8锁现象【8个锁的问题】
  • 六、集合类不安全
    • 1.List不安全
      • ①Vector底层是使用synchronized关键字来实现的:效率特别低下。
      • ②Collections.synchronizedList是利用给所有的方法加了锁 转换集合[方案二] 不过太简单粗暴,降低并发量
      • ③CopyOnWriteArrayList()写时不复制,写时再去复制【底层用了violidate和transient】
    • 2.Set不安全
    • 3.Map不安全
    • 4.阻塞队列下一章会讲解使用
  • 七、阻塞队列
    • 1.概念定义
    • 2.为何要使用?
    • 3.如何学会使用队列
      • ①添加:add 移除:remove =>抛出异常
      • ②添加:offer 移除:poll =>无返回值,不跑出异常
      • ③添加:put 移除:take =>等待
      • ④添加:offer 移除:poll =>超时等待
    • 4.SynchronizedQueue同步队列
  • 八、Callable
    • 1.源码分析
      • ①首先Thread
      • ②看看Runnable的实现类FutureTask
    • 2.代码
  • 九、常用辅助类
    • ①CountDownLatch 减法计数器
    • ②CyclickBarrier 加法计数器
    • ③Semaphone 信号量
  • 十、读写锁
  • 十一、线程池
    • 1.池化技术概述
    • 2.三大方法
      • ①方法源码
      • ②代码
    • 3.七种参数
    • 4.四种拒绝策略
    • 5.设置池的大小
  • 十二、四大函数式接口
    • ①Function 函数式接口
    • ②Consumer 消费式接口
    • ③Predicate 断定型接口
    • ④Supplier 供给型接口
  • 十三、Stream流式计算
  • 十四、ForkJoin
    • 1.什么是ForkJoin?
    • 2.ForkJoin特点:工作窃取
    • 3.如何使用ForkJoin
    • 4.其他两种方式求和汇总
    • 5.reduce方法
  • 十五、异步回调
    • 1.没有返回值的runAsync异步回调
    • 2.有返回值的supply Async异步回调
  • 十六、JMM【回顾多线程的课程即可】
  • 十七、Volatile
    • ①保证可见性
    • ②不保证原子性
    • ③禁止指令重排
  • 十八、深入单例模式【只要是单例 构造器一定要私有化】
    • ①饿汉式
    • DLC懒汉式
      • 问题1:只能用于单线程,无法使用多线程的问题
      • 问题2:发现new对象 不是一个原子性操作,会造成指令重排的可能
      • 问题3:反射会破坏上面单例模式
      • 问提4:发现单例又反射被破坏了
      • 问提5:红绿灯标记被人知道了,单例模式被反射破解
    • ③枚举类:
    • ④静态内部类
  • 十九、深入理解CAS
    • 1.什么是CAS?
    • 2.unsafe
      • ①点先这个U。
      • ②点这个getAndInt
    • 3.总结
    • 4.ABA
  • 二十、原子引用
  • 知识点复习图

一、什么是JUC?

多线程进阶=>高并发JUC学习笔记_第1张图片
多线程进阶=>高并发JUC学习笔记_第2张图片

二、线程与进程

①基础

多线程进阶=>高并发JUC学习笔记_第3张图片

②线程状态State

多线程进阶=>高并发JUC学习笔记_第4张图片
多线程进阶=>高并发JUC学习笔记_第5张图片

③并发与并行

多线程进阶=>高并发JUC学习笔记_第6张图片
并发编程本质:充分利用CPU资源

④wait与sleep区别

多线程进阶=>高并发JUC学习笔记_第7张图片

三、Lock锁

①传统Synchronized方法

多线程进阶=>高并发JUC学习笔记_第8张图片
在这里插入图片描述

②Lock锁

多线程进阶=>高并发JUC学习笔记_第9张图片
多线程进阶=>高并发JUC学习笔记_第10张图片
多线程进阶=>高并发JUC学习笔记_第11张图片

③Synchronized与Lock的区别

多线程进阶=>高并发JUC学习笔记_第12张图片

④各种锁

1.(非)公平锁

公平锁:非常公平,不能够插队,必须先来后到!
非公平锁:非常不公平,可以插队[默认是非公平锁]
多线程进阶=>高并发JUC学习笔记_第13张图片

2.可重入锁(递归锁)

多线程进阶=>高并发JUC学习笔记_第14张图片

(1)Synchronized版本

多线程进阶=>高并发JUC学习笔记_第15张图片
多线程进阶=>高并发JUC学习笔记_第16张图片

(2)Lock版

多线程进阶=>高并发JUC学习笔记_第17张图片
多线程进阶=>高并发JUC学习笔记_第18张图片

3.死锁

就不做过多介绍,这里截图在多线程的例子
多线程进阶=>高并发JUC学习笔记_第19张图片
多线程进阶=>高并发JUC学习笔记_第20张图片
多线程进阶=>高并发JUC学习笔记_第21张图片
多线程进阶=>高并发JUC学习笔记_第22张图片
多线程进阶=>高并发JUC学习笔记_第23张图片
多线程进阶=>高并发JUC学习笔记_第24张图片

4.自旋锁[自定义锁]

多线程进阶=>高并发JUC学习笔记_第25张图片
多线程进阶=>高并发JUC学习笔记_第26张图片
运行结果:
B进程必须等待A进程Unlock后,才能Unlock,在这之前进行自旋等待。。。。

5.死锁排查

多线程进阶=>高并发JUC学习笔记_第27张图片
多线程进阶=>高并发JUC学习笔记_第28张图片
面试,工作中! 排查问题:
1、日志 9 成
2、堆栈 1成

四、生产者和消费者问题

1.Synchronized版本

多线程进阶=>高并发JUC学习笔记_第29张图片
多线程进阶=>高并发JUC学习笔记_第30张图片
多线程进阶=>高并发JUC学习笔记_第31张图片
多线程进阶=>高并发JUC学习笔记_第32张图片
多线程进阶=>高并发JUC学习笔记_第33张图片

2.Lock版

多线程进阶=>高并发JUC学习笔记_第34张图片
多线程进阶=>高并发JUC学习笔记_第35张图片
多线程进阶=>高并发JUC学习笔记_第36张图片
多线程进阶=>高并发JUC学习笔记_第37张图片
然后如何做到准确通知和唤醒?而不是随机=>
多线程进阶=>高并发JUC学习笔记_第38张图片
多线程进阶=>高并发JUC学习笔记_第39张图片
多线程进阶=>高并发JUC学习笔记_第40张图片
多线程进阶=>高并发JUC学习笔记_第41张图片

五、8锁现象【8个锁的问题】

在这里插入图片描述
多线程进阶=>高并发JUC学习笔记_第42张图片
多线程进阶=>高并发JUC学习笔记_第43张图片
在这里插入图片描述
多线程进阶=>高并发JUC学习笔记_第44张图片
多线程进阶=>高并发JUC学习笔记_第45张图片
在这里插入图片描述
多线程进阶=>高并发JUC学习笔记_第46张图片
多线程进阶=>高并发JUC学习笔记_第47张图片
多线程进阶=>高并发JUC学习笔记_第48张图片
多线程进阶=>高并发JUC学习笔记_第49张图片
多线程进阶=>高并发JUC学习笔记_第50张图片
在这里插入图片描述
多线程进阶=>高并发JUC学习笔记_第51张图片
多线程进阶=>高并发JUC学习笔记_第52张图片
多线程进阶=>高并发JUC学习笔记_第53张图片
多线程进阶=>高并发JUC学习笔记_第54张图片
多线程进阶=>高并发JUC学习笔记_第55张图片
多线程进阶=>高并发JUC学习笔记_第56张图片
多线程进阶=>高并发JUC学习笔记_第57张图片
多线程进阶=>高并发JUC学习笔记_第58张图片

六、集合类不安全

多线程进阶=>高并发JUC学习笔记_第59张图片

1.List不安全

多线程进阶=>高并发JUC学习笔记_第60张图片

①Vector底层是使用synchronized关键字来实现的:效率特别低下。

多线程进阶=>高并发JUC学习笔记_第61张图片

②Collections.synchronizedList是利用给所有的方法加了锁 转换集合[方案二] 不过太简单粗暴,降低并发量

多线程进阶=>高并发JUC学习笔记_第62张图片

③CopyOnWriteArrayList()写时不复制,写时再去复制【底层用了violidate和transient】

多线程进阶=>高并发JUC学习笔记_第63张图片

2.Set不安全

多线程进阶=>高并发JUC学习笔记_第64张图片
new HashSet底层原理,实际上是HashMap
多线程进阶=>高并发JUC学习笔记_第65张图片
例子
多线程进阶=>高并发JUC学习笔记_第66张图片

3.Map不安全

多线程进阶=>高并发JUC学习笔记_第67张图片
new HashMap底层
多线程进阶=>高并发JUC学习笔记_第68张图片
例子
多线程进阶=>高并发JUC学习笔记_第69张图片
解决方案
多线程进阶=>高并发JUC学习笔记_第70张图片
多线程进阶=>高并发JUC学习笔记_第71张图片

4.阻塞队列下一章会讲解使用

七、阻塞队列

1.概念定义

多线程进阶=>高并发JUC学习笔记_第72张图片
多线程进阶=>高并发JUC学习笔记_第73张图片
多线程进阶=>高并发JUC学习笔记_第74张图片
多线程进阶=>高并发JUC学习笔记_第75张图片
多线程进阶=>高并发JUC学习笔记_第76张图片
多线程进阶=>高并发JUC学习笔记_第77张图片
在这里插入图片描述

2.为何要使用?

多线程进阶=>高并发JUC学习笔记_第78张图片

3.如何学会使用队列

操作是添加、删除
实际要学的是一下四组API
多线程进阶=>高并发JUC学习笔记_第79张图片

①添加:add 移除:remove =>抛出异常

多线程进阶=>高并发JUC学习笔记_第80张图片

②添加:offer 移除:poll =>无返回值,不跑出异常

多线程进阶=>高并发JUC学习笔记_第81张图片

③添加:put 移除:take =>等待

多线程进阶=>高并发JUC学习笔记_第82张图片

④添加:offer 移除:poll =>超时等待

多线程进阶=>高并发JUC学习笔记_第83张图片

4.SynchronizedQueue同步队列

多线程进阶=>高并发JUC学习笔记_第84张图片
多线程进阶=>高并发JUC学习笔记_第85张图片
多线程进阶=>高并发JUC学习笔记_第86张图片

八、Callable

多线程进阶=>高并发JUC学习笔记_第87张图片
多线程进阶=>高并发JUC学习笔记_第88张图片

1.源码分析

①首先Thread

多线程进阶=>高并发JUC学习笔记_第89张图片
看出 只能传入Runnalbe的参数

②看看Runnable的实现类FutureTask

多线程进阶=>高并发JUC学习笔记_第90张图片
这样我们就可以先把Callable 放入到FutureTask中, 如何再把FutureTask 放入到Thread就可以

2.代码

多线程进阶=>高并发JUC学习笔记_第91张图片

九、常用辅助类

①CountDownLatch 减法计数器

多线程进阶=>高并发JUC学习笔记_第92张图片
多线程进阶=>高并发JUC学习笔记_第93张图片

②CyclickBarrier 加法计数器

多线程进阶=>高并发JUC学习笔记_第94张图片
多线程进阶=>高并发JUC学习笔记_第95张图片

③Semaphone 信号量

抢车位:3个停车位 6个车
多线程进阶=>高并发JUC学习笔记_第96张图片
多线程进阶=>高并发JUC学习笔记_第97张图片

十、读写锁

多线程进阶=>高并发JUC学习笔记_第98张图片
多线程进阶=>高并发JUC学习笔记_第99张图片
多线程进阶=>高并发JUC学习笔记_第100张图片
多线程进阶=>高并发JUC学习笔记_第101张图片
多线程进阶=>高并发JUC学习笔记_第102张图片
多线程进阶=>高并发JUC学习笔记_第103张图片
多线程进阶=>高并发JUC学习笔记_第104张图片
多线程进阶=>高并发JUC学习笔记_第105张图片
多线程进阶=>高并发JUC学习笔记_第106张图片

十一、线程池

线程池:三大方法、7大参数、4种拒绝策略

1.池化技术概述

在这里插入图片描述
多线程进阶=>高并发JUC学习笔记_第107张图片
在这里插入图片描述
在这里插入图片描述

2.三大方法

①方法源码

多线程进阶=>高并发JUC学习笔记_第108张图片
多线程进阶=>高并发JUC学习笔记_第109张图片
多线程进阶=>高并发JUC学习笔记_第110张图片

②代码

多线程进阶=>高并发JUC学习笔记_第111张图片
多线程进阶=>高并发JUC学习笔记_第112张图片

3.七种参数

多线程进阶=>高并发JUC学习笔记_第113张图片
多线程进阶=>高并发JUC学习笔记_第114张图片
多线程进阶=>高并发JUC学习笔记_第115张图片
代码:
多线程进阶=>高并发JUC学习笔记_第116张图片

4.四种拒绝策略

多线程进阶=>高并发JUC学习笔记_第117张图片
在这里插入图片描述

5.设置池的大小

多线程进阶=>高并发JUC学习笔记_第118张图片
多线程进阶=>高并发JUC学习笔记_第119张图片
多线程进阶=>高并发JUC学习笔记_第120张图片

十二、四大函数式接口

多线程进阶=>高并发JUC学习笔记_第121张图片

①Function 函数式接口

多线程进阶=>高并发JUC学习笔记_第122张图片
多线程进阶=>高并发JUC学习笔记_第123张图片

②Consumer 消费式接口

多线程进阶=>高并发JUC学习笔记_第124张图片
多线程进阶=>高并发JUC学习笔记_第125张图片

③Predicate 断定型接口

多线程进阶=>高并发JUC学习笔记_第126张图片
多线程进阶=>高并发JUC学习笔记_第127张图片

④Supplier 供给型接口

多线程进阶=>高并发JUC学习笔记_第128张图片
多线程进阶=>高并发JUC学习笔记_第129张图片

十三、Stream流式计算

大数据:存储+计算
存储:集合|MySQL
计算:交给流来操作
多线程进阶=>高并发JUC学习笔记_第130张图片
多线程进阶=>高并发JUC学习笔记_第131张图片
多线程进阶=>高并发JUC学习笔记_第132张图片

十四、ForkJoin

1.什么是ForkJoin?

在jdk1.7,并行执行任务!提高效率,大数据量!
大数据:Map Reduce(吧大任务拆分成小任务)
多线程进阶=>高并发JUC学习笔记_第133张图片

2.ForkJoin特点:工作窃取

实现原理是:双端队列!从上面和下面都可以去拿到任务进行执行!
多线程进阶=>高并发JUC学习笔记_第134张图片

3.如何使用ForkJoin

多线程进阶=>高并发JUC学习笔记_第135张图片
多线程进阶=>高并发JUC学习笔记_第136张图片
多线程进阶=>高并发JUC学习笔记_第137张图片
多线程进阶=>高并发JUC学习笔记_第138张图片

4.其他两种方式求和汇总

多线程进阶=>高并发JUC学习笔记_第139张图片

5.reduce方法

多线程进阶=>高并发JUC学习笔记_第140张图片

十五、异步回调

Future 设计的初衷:对将来的某个事件结果进行建模
其实就是前端 --> 发送ajax异步请求给后端,
但是我们平时都使用CompletableFuture
多线程进阶=>高并发JUC学习笔记_第141张图片
在这里插入图片描述
步骤:异步执行=>成功回调+失败回调

1.没有返回值的runAsync异步回调

多线程进阶=>高并发JUC学习笔记_第142张图片

2.有返回值的supply Async异步回调

多线程进阶=>高并发JUC学习笔记_第143张图片
多线程进阶=>高并发JUC学习笔记_第144张图片

十六、JMM【回顾多线程的课程即可】

多线程进阶=>高并发JUC学习笔记_第145张图片

十七、Volatile

Volatile 是 Java 虚拟机提供 轻量级的同步机制
1、保证可见性
2、不保证原子性
3、禁止指令重排

①保证可见性

多线程进阶=>高并发JUC学习笔记_第146张图片
多线程进阶=>高并发JUC学习笔记_第147张图片

②不保证原子性

原子性:不可分割;
线程A在执行任务的时候,不能被打扰的,也不能被分割的,要么同时成功,要么同时失败.
保证原子性:lock、synchhronized外 还有CAS
多线程进阶=>高并发JUC学习笔记_第148张图片
CAS:利用原子类
多线程进阶=>高并发JUC学习笔记_第149张图片
这些类的底层都直接和操作系统挂钩!是在内存中修改值。

③禁止指令重排

多线程进阶=>高并发JUC学习笔记_第150张图片
多线程进阶=>高并发JUC学习笔记_第151张图片
多线程进阶=>高并发JUC学习笔记_第152张图片
多线程进阶=>高并发JUC学习笔记_第153张图片

十八、深入单例模式【只要是单例 构造器一定要私有化】

①饿汉式

多线程进阶=>高并发JUC学习笔记_第154张图片

DLC懒汉式

需要的时候再创建,节省空间。

问题1:只能用于单线程,无法使用多线程的问题

多线程进阶=>高并发JUC学习笔记_第155张图片
改进=>加锁
多线程进阶=>高并发JUC学习笔记_第156张图片

问题2:发现new对象 不是一个原子性操作,会造成指令重排的可能

改进=> 加volatile
多线程进阶=>高并发JUC学习笔记_第157张图片

问题3:反射会破坏上面单例模式

多线程进阶=>高并发JUC学习笔记_第158张图片
改进=>在构造器加吧锁
多线程进阶=>高并发JUC学习笔记_第159张图片

问提4:发现单例又反射被破坏了

不用上面写的getInstance(),而是全用构造器创建对象,发现单例又被破坏了
多线程进阶=>高并发JUC学习笔记_第160张图片
改进=>加一个标志:红绿灯
多线程进阶=>高并发JUC学习笔记_第161张图片

问提5:红绿灯标记被人知道了,单例模式被反射破解

发现红绿灯标志被知道了:不管怎么写,总有人会解密知道这个
多线程进阶=>高并发JUC学习笔记_第162张图片

③枚举类:

点进去看下源码
多线程进阶=>高并发JUC学习笔记_第163张图片

多线程进阶=>高并发JUC学习笔记_第164张图片
新建一个枚举类
多线程进阶=>高并发JUC学习笔记_第165张图片
可是这边target却有写空参构造法
多线程进阶=>高并发JUC学习笔记_第166张图片
探究:
多线程进阶=>高并发JUC学习笔记_第167张图片
所以
多线程进阶=>高并发JUC学习笔记_第168张图片
源码
在这里插入图片描述
所以确实反射不能破坏枚举类

④静态内部类

多线程进阶=>高并发JUC学习笔记_第169张图片

十九、深入理解CAS

1.什么是CAS?

多线程进阶=>高并发JUC学习笔记_第170张图片

2.unsafe

在这里插入图片描述

①点先这个U。

getAndInt留给②去点.
多线程进阶=>高并发JUC学习笔记_第171张图片

②点这个getAndInt

多线程进阶=>高并发JUC学习笔记_第172张图片
多线程进阶=>高并发JUC学习笔记_第173张图片
还采用了自旋锁[do whie]

3.总结

CAS:比较当前工作内存中的值 和 主内存中的值,如果这个值是期望的,那么则执行操作!如果不是就一直循环,使用的是自旋锁。
缺点:
①循环会耗时;
②一次性只能保证一个共享变量的原子性;
③它会存在ABA问题

4.ABA

多线程进阶=>高并发JUC学习笔记_第174张图片
多线程进阶=>高并发JUC学习笔记_第175张图片

二十、原子引用

解决ABA问题,对应的思想:就是使用了乐观锁~
带版本号的 原子操作!
多线程进阶=>高并发JUC学习笔记_第176张图片
多线程进阶=>高并发JUC学习笔记_第177张图片
多线程进阶=>高并发JUC学习笔记_第178张图片
总结:取自bilibli狂神

知识点复习图

多线程进阶=>高并发JUC学习笔记_第179张图片
多线程进阶=>高并发JUC学习笔记_第180张图片
多线程进阶=>高并发JUC学习笔记_第181张图片

你可能感兴趣的:(多线程进阶=>高并发JUC学习笔记)