Java JUC编程

JUC基础

  • 概念
    1. 进程: 一个程序
    2. 线程: 单独的资源类,没有任何附属操作
    3. 并发:多个线程同时操作一个资源类 -->单核: 模拟多个线程, 多个线程快速交替运行
      • 并发编程的本质:充分利用CPU的资源
    4. 并行:多个人一起行走 --> 多核:多个线程可以同时运行 --> 线程池
  • Java默认两个线程
    • main / GC
  • java开启线程的3个方式
    • Thread / runnable / callable
  • java只能通过本地方法开启线程,本身没有权限
  • 线程的六种状态

thread.State=

  • wait/sleep区别
    1. 来自不同的类
      wait -- > Object类
      sleep --> Thread类
      企业一般用TimeUtil
    2. 是否释放锁
      wait -- > 释放锁
      sleep --> 抱着锁睡觉
    3. 使用范围不同
      wait -- > 必须在同步代码块中使用
      sleep --> 任何地方都可以
    4. 是否需要捕获异常
      wait -- > 不需要
      sleep --> 必须要,有超时等待的情况

lambda表达式

  • 本质: 函数式接口的实现类的实例化对象
  • 简化后为: 接口方法的简写 (方法的参数...)->
  • 规则:
    1. 参数列表可以省略参数类型;多个参数时都一起省略,加()包裹
    2. 函数题有多行语句时,大括号不能省;一条语句时可以省略
    3. 接口必须是函数式接口,即接口只有1个方法

synchronized

  • 本质: 队列+锁
  • 锁: 对象 / class

Lock锁

  • 接口:
    • 3个实现类 可重入锁 / 读锁 / 写锁
    • 方法:lock / unlock
  • 构造函数
    • 非公平锁(默认) : 可以插队
    • 公平锁: 带boolern参数: 先来后到,排队
  • 使用步骤
    1. new 实现类的锁
    2. 加锁:代码写在try catch中
    3. 解锁: 写在finally中
  • synchronized和lock的区别
    1. synchronized是java关键字,自动挡; lock是java类,手动挡
    2. synchronized无法判断是否获取锁的状态;lock可以判断获是否获取到了锁
    3. synchronized自动释放锁;lock必须手动释放,如果不释放 --> 死锁
    4. synchronized线程一致等待;lock 线程不一定一直等待
    5. synchronized 可重入,不可中断,非公平;lock 可重入,可以判断锁,非公平(可设置)
    6. synchronized 适合少量的代码同步;lock 适合大量的代码同步
  • lock锁的优势
    Condition类:实现 精准的通知和唤醒线程
  • 8锁问题
    • 锁是什么,锁的是谁?
      锁: 对象, new出来的,可以多个
      锁:class,锁模版, 唯一一个

**集合类不安全

  1. List线程不安全
  2. Set线程不安全
    • HashSet的本质是HashMap的key,不能重复
  3. Map不安全
  4. **ConcurrentHashMap的原理研究?

Callable

  • 区别: 相比runable的区别 --> run方法
    有返回值、可抛出异常、方法不同 --> call方法
  • 特点
    1. 有缓存
    2. 结果需要等待,可能会阻塞

常用辅助类

  1. CountDownLatch 减法计数器
  2. CyclicBarrier 加法计数器
  3. Semaphore 信号量

读写锁

  • 特点
    读可以被多个线程读,写只能由1个线程写入
  • ReadWriteLock
    • 独占锁:写锁:一次只能被一个线程占用
    • 共享锁:读锁:多个线程可以同时占用
    • 读可以被多个线程读,写只能由1个线程写入
    • 读-读:多线程可以共存
    • 读-写:多线程不能共存
    • 写-写:多线程不能共存

阻塞队列 blockingQueue

  • 其他相关类
    • 非阻塞队列 AbstractQueue
    • deque:双端队列: 可以从两端取
  • 使用
    1. 方式: 添加、移除、判断首部
    2. 四组API:
    • 抛出异常
    • 不会抛出异常
    • 阻塞等待
    • 超时等待
  • SynchronousQueue同步队列
    • 写入一个后,只能等下一个出来才能再写入,容量为0

线程池

  1. 池化技术:准备好一些资源,有人需要就去拿,用完还给我
  2. 线程池的优点
    • 降低资源消耗
    • 提高响应速度
    • 方便管理
  3. 作用:管理线程、控制最大并发数、线程复用
  4. 必考:
    • 三大方法:创建线程池的3个方式
      • 本质: 调用ThreadPoolExecutor根据7个参数来创建
    • 7大参数:创建线程池的7个参数
    • 4种拒绝策略
  5. 最大线程数该如何设置?
    • CPU密集型: CPU并行处理,效率最高; 电脑几核就设置为几
    • IO密集型: 大于程序中十分消耗资源的IO的线程数

4大函数式接口

  • 概念: 函数式接口:简化编程模型
  1. predicate: 断定型接口
  2. function:函数式接口
  3. supplier:供给型接口
  4. consumer:消费型接口

stream流式计算

ForkJoin 分支合并

  • 并行执行,提高效率,大数据量
    大数据: map reduce : 将大任务拆分成小任务
  • 特点:工作窃取: 提高效率,双端队列

异步回调

JMM

  1. volatile
  • 保证可见性: 主内存值有变动, 线程自动更新
  • 不保证原子性:不保证不可分割
  • 禁止指令重排
    • 概念: 计算机并不是按照写的程序那样执行
      源代码 --> 编译器优化的重排--> 指令并行也可能重排--> 内存系统也可能重排--> 执行
    • 指令重排: 处理器会考虑程序依赖性的问题
    • 内存屏障-->CPU指令
      • 保证特定操作的执行顺序
      • 保证某些变量的可见性
    • 加了volatile,系统会在该语句前后加内存屏障,让上下文程序不与该语句执行顺序发送交换
    • 内存屏障在单例模式中使用较多
  1. JMM: java内存模型,概念
  • 关于JMM的约定
    1. 线程解锁前,必须立即将共享变量刷回主内存
    2. 线程加锁前,必须读取主内存中的最新值到自己的工作内存中
    3. 加锁和解锁是同一把锁
  • 8种操作
    四组操作:read/load - use/assign - write/store - lock/unlock:必须成对执行
  1. 单例模式
    • 饿汉式
    • DCL懒汉式
    • 内部类
    • 枚举

CAS

  • cas: 比较当前内存中的值和主内存中的值,如果是期望的就更新;否则不更新,如果不是一直循环; 配合自旋锁,一直判断
  • 缺点:
    1. 自旋判断,耗时
    2. 一次只能保证一个共享变量的原子性
    3. 存在ABA问题
  • ABA问题 狸猫换太子

原子引用

  • 带版本号的原子操作 -- > 解决ABA问题 引入AtomicStampedReference类
  • 对应的思想: 乐观锁

各种锁

  1. 公平锁和非公平锁:是否可以插队
    • 公平锁: 先来后到
    • 非公平锁: 可以插队(默认)
  2. 可重入锁(递归锁)
    • 拿到了外面的锁,自动拿到了里面的锁; -->. 注意锁要配对
  3. 自旋锁: 不断尝试直到成功
  4. 死锁
    • 概念: 两个线程互相拥有对方正在抢的锁
    • 解决:
      1. 使用jps定位进程号 jps -l
      2. 使用jstack 进程号 查看进程堆栈信息,从而找到死锁问题
      3. 可以查看日志
posted @ 2022-02-27 14:39  蓝天可乐  阅读(70)  评论(0)    收藏  举报