阻塞队列
线程池
>线程的7个状态⛄️
[ *创建🆕 ]new
[ *就绪🧍 ]
[ *运行🏃 ]
[ *阻塞🚪 ]block
[ *销毁💀 ]terminate
[ 等待🧊 ]wait
[ 限时等待💤 ]time-wait
waiting 和 notifly的区别
wait等待 会释放锁
锁释放 另一个线程就进来了
notify 唤醒 唤醒的是持有锁的某一个线程
sleep 不会释放锁
wait/notify : 只能同步代码块使用 Object
任意对象都可以是锁对象
sleep:
线程池7大构造参数
拒绝策略(核心线程数满 队列满 最大线程数)
运行流程:线程池和核心线程
最大线程会把 这个线程销毁,仅保存核心线程
new ThreadPoolExecutor(10,100,60,TimeUnit)
new Array
JUC 提供工具类 Single单个线程
缓存线程池 核心线程数 0 最大线程数Interger 最大值
同步队列 没有容量 提交一对拿一 创建多少个线程取决于任务量
取决于任务量
创建一个任务调度的线程池
JUC 提供工具
创建 单线程池 固定大小 缓存线程池 任务调度池
donwNow 立即停止
donw 提交的任务会把已安排的任务先执行完
单线程
机器指令和所指定指令集不同 需要指令重排序
要想多线程准确无误执行 原子性 可见性 有序性 才能保证程序运行不出错,否则可能程序导致不一致
原子性:一次一个线程执行
可见性:AB访问同变量,A改B可见被改,
主线程堆资源修改 子线程看不到 没有可见性 涉及到JMM模型
Java emory Model
主存 仅一个主线程的本地内存
每一个线程都有自己的本地内存
JMM 模型
volatile 修饰词 特点:被修饰 保证线程之间变量的 “可见性”
修改主存中的值
先从主存中读取这个值
volatile有序性,可见性,不能解决原子性
conut++ – 不是原子性
JMM java内存模型 2条规范
线程解锁前,不许把工作内存共享变量的,如果值做了更改刷新到主内存中
线程加锁时,清楚本地的值,然后加载
javap -v 看到程序运行后的结果
volatiile 与 synchronized 区别
synchronized 三个特性都能保证
锁优化
阻塞 解除阻塞:用户态 内核态 切换
JVM 阻塞优化: 尽量不要阻塞
自旋锁:操作时,加了同步块,不会立刻进入阻塞,执行一部分无意义的循环,不是等待睡眠。无意义的执行 CPU依然执行,同步代码块 锁被释放。执行无意义的循环就去获取锁。(主要为了不被CPU挂起)
自旋锁:后面的线程执行无意义的循环,如果第一个占有时间长,会占有CPU时间的。 第一次自选成功率高,后面的自选成功率也高。
1.6后适应性自旋锁 变得更聪明 :如果第一次自选成功率低,后面则会进入阻塞。
有一些JDK 内置API 自动加锁 ,如果不需要 ,则会 锁消除
尽量缩小锁的范围 不需要的业务,不使用锁
用户态 内核态 频繁切换
,ghjkfghjhgfdsgz
锁粗化 : 频繁切换 加大锁的范围 ,避免状态切换,减少CPU的消耗