Java JUC编程
JUC基础
- 概念
- 进程: 一个程序
- 线程: 单独的资源类,没有任何附属操作
- 并发:多个线程同时操作一个资源类 -->单核: 模拟多个线程, 多个线程快速交替运行
- 并发编程的本质:充分利用CPU的资源
- 并行:多个人一起行走 --> 多核:多个线程可以同时运行 --> 线程池
- Java默认两个线程
- main / GC
- java开启线程的3个方式
- Thread / runnable / callable
- java只能通过本地方法开启线程,本身没有权限
- 线程的六种状态
thread.State=
- wait/sleep区别
- 来自不同的类
wait -- > Object类
sleep --> Thread类
企业一般用TimeUtil - 是否释放锁
wait -- > 释放锁
sleep --> 抱着锁睡觉 - 使用范围不同
wait -- > 必须在同步代码块中使用
sleep --> 任何地方都可以 - 是否需要捕获异常
wait -- > 不需要
sleep --> 必须要,有超时等待的情况
- 来自不同的类
lambda表达式
- 本质: 函数式接口的实现类的实例化对象
- 简化后为: 接口方法的简写 (方法的参数...)->
- 规则:
- 参数列表可以省略参数类型;多个参数时都一起省略,加()包裹
- 函数题有多行语句时,大括号不能省;一条语句时可以省略
- 接口必须是函数式接口,即接口只有1个方法
synchronized
- 本质: 队列+锁
- 锁: 对象 / class
Lock锁
- 接口:
- 3个实现类 可重入锁 / 读锁 / 写锁
- 方法:lock / unlock
- 构造函数
- 非公平锁(默认) : 可以插队
- 公平锁: 带boolern参数: 先来后到,排队
- 使用步骤
- new 实现类的锁
- 加锁:代码写在try catch中
- 解锁: 写在finally中
- synchronized和lock的区别
- synchronized是java关键字,自动挡; lock是java类,手动挡
- synchronized无法判断是否获取锁的状态;lock可以判断获是否获取到了锁
- synchronized自动释放锁;lock必须手动释放,如果不释放 --> 死锁
- synchronized线程一致等待;lock 线程不一定一直等待
- synchronized 可重入,不可中断,非公平;lock 可重入,可以判断锁,非公平(可设置)
- synchronized 适合少量的代码同步;lock 适合大量的代码同步
- lock锁的优势
Condition类:实现 精准的通知和唤醒线程 - 8锁问题
- 锁是什么,锁的是谁?
锁: 对象, new出来的,可以多个
锁:class,锁模版, 唯一一个
- 锁是什么,锁的是谁?
**集合类不安全
- List线程不安全
- Set线程不安全
- HashSet的本质是HashMap的key,不能重复
- Map不安全
- **ConcurrentHashMap的原理研究?
Callable
- 区别: 相比runable的区别 --> run方法
有返回值、可抛出异常、方法不同 --> call方法 - 特点
- 有缓存
- 结果需要等待,可能会阻塞
常用辅助类
- CountDownLatch 减法计数器
- CyclicBarrier 加法计数器
- Semaphore 信号量
读写锁
- 特点
读可以被多个线程读,写只能由1个线程写入 - ReadWriteLock
- 独占锁:写锁:一次只能被一个线程占用
- 共享锁:读锁:多个线程可以同时占用
- 读可以被多个线程读,写只能由1个线程写入
- 读-读:多线程可以共存
- 读-写:多线程不能共存
- 写-写:多线程不能共存
阻塞队列 blockingQueue
- 其他相关类
- 非阻塞队列 AbstractQueue
- deque:双端队列: 可以从两端取
- 使用
- 方式: 添加、移除、判断首部
- 四组API:
- 抛出异常
- 不会抛出异常
- 阻塞等待
- 超时等待
- SynchronousQueue同步队列
- 写入一个后,只能等下一个出来才能再写入,容量为0
线程池
- 池化技术:准备好一些资源,有人需要就去拿,用完还给我
- 线程池的优点
- 降低资源消耗
- 提高响应速度
- 方便管理
- 作用:管理线程、控制最大并发数、线程复用
- 必考:
- 三大方法:创建线程池的3个方式
- 本质: 调用ThreadPoolExecutor根据7个参数来创建
- 7大参数:创建线程池的7个参数
- 4种拒绝策略
- 三大方法:创建线程池的3个方式
- 最大线程数该如何设置?
- CPU密集型: CPU并行处理,效率最高; 电脑几核就设置为几
- IO密集型: 大于程序中十分消耗资源的IO的线程数
4大函数式接口
- 概念: 函数式接口:简化编程模型
- predicate: 断定型接口
- function:函数式接口
- supplier:供给型接口
- consumer:消费型接口
stream流式计算
ForkJoin 分支合并
- 并行执行,提高效率,大数据量
大数据: map reduce : 将大任务拆分成小任务 - 特点:工作窃取: 提高效率,双端队列
异步回调
JMM
- volatile
- 保证可见性: 主内存值有变动, 线程自动更新
- 不保证原子性:不保证不可分割
- 禁止指令重排
- 概念: 计算机并不是按照写的程序那样执行
源代码 --> 编译器优化的重排--> 指令并行也可能重排--> 内存系统也可能重排--> 执行 - 指令重排: 处理器会考虑程序依赖性的问题
- 内存屏障-->CPU指令
- 保证特定操作的执行顺序
- 保证某些变量的可见性
- 加了volatile,系统会在该语句前后加内存屏障,让上下文程序不与该语句执行顺序发送交换
- 内存屏障在单例模式中使用较多
- 概念: 计算机并不是按照写的程序那样执行
- JMM: java内存模型,概念
- 关于JMM的约定
- 线程解锁前,必须立即将共享变量刷回主内存
- 线程加锁前,必须读取主内存中的最新值到自己的工作内存中
- 加锁和解锁是同一把锁
- 8种操作
四组操作:read/load - use/assign - write/store - lock/unlock:必须成对执行
- 单例模式
- 饿汉式
- DCL懒汉式
- 内部类
- 枚举
CAS
- cas: 比较当前内存中的值和主内存中的值,如果是期望的就更新;否则不更新,如果不是一直循环; 配合自旋锁,一直判断
- 缺点:
- 自旋判断,耗时
- 一次只能保证一个共享变量的原子性
- 存在ABA问题
- ABA问题 狸猫换太子
原子引用
- 带版本号的原子操作 -- > 解决ABA问题 引入AtomicStampedReference类
- 对应的思想: 乐观锁
各种锁
- 公平锁和非公平锁:是否可以插队
- 公平锁: 先来后到
- 非公平锁: 可以插队(默认)
- 可重入锁(递归锁)
- 拿到了外面的锁,自动拿到了里面的锁; -->. 注意锁要配对
- 自旋锁: 不断尝试直到成功
- 死锁
- 概念: 两个线程互相拥有对方正在抢的锁
- 解决:
- 使用jps定位进程号 jps -l
- 使用jstack 进程号 查看进程堆栈信息,从而找到死锁问题
- 可以查看日志
浙公网安备 33010602011771号