线程生命周期
NEW:使用 new 操作符创建的新的线程对象的初始状态
RUNNABLE:可运行状态,又分为两种
READY:RUNNING状态的线程 被调度/yield ,线程变为READY
RUNNING:READY的线程被调度,变成变为RUNNAING
TERMINATED:RUNNABLE的线程执行完毕,一般是run方法中的逻辑执行完毕
BLOCKED:RUNNABLE状态的线程调用同步代码块,拿不到锁的时候
WAITING:RUNNABLE状态的线程调用wait、join、LockSupport.park方法的时候
TIME_WAITING:同WAITING,不过是方法中参数带时间,如sleep(时间)
线程的中断和复位
终止:
thread.interrupt()方法底层是通过设置一个boolean的标志位来标志线程是否应该终端,调用该方法可以将中断标志位设置为true
thread.currentThread.isInterrupt()可以获得底层的中断标志位
重置:
Thread.interrupted()可以使中断标志位复位(回到初始状态false)
中断一个处于阻塞状态(join、wait、sleep、queue.take)的线程,会抛出InterruptedException(相当于系统给了一个停止阻塞线程的入口,可捕获异常处理)
线程抛出InterruptedException也会重置中断标志位
锁升级
偏向锁(cas乐观锁):只有同一个线程去访问(绝大多时候)
轻量级锁(自旋锁):两个线程交替访问(绝大部分线程载获得锁以后,会在非常短的时间内释放) -> 自旋(线程释放锁很快,一直循环重试,反而效率很高)
问题:自旋会占用CPU资源,所以在指定的自旋次数后,还没有获得轻量级锁,锁会膨胀成重量级锁 -> 阻塞
自旋次数:1、设置(preBlockSpin 默认为10) 2、 自适应自旋
重量级锁(Mutex):多个线程同时访问 阻塞(升级到重量级锁之后,没有获得锁的线程会被阻塞 BLOCKED)
monitorEnter ------【Monitor】------monitorEnter成功------获得对象锁 ------ monitorExit
每一个对象都有一个ObjectMonitor