线程六大状态
根据Thread类中定义的枚举类型State
值,可以看出有6中状态:
1 | public enum State { |
新建
状态 NEW新建了Thread类对象,但是没有启动的线程。
new Thread()
可运行
状态 RUNNABLE线程对象新建后,调用
start()
方法即处于了RUNNABLE
状态。- 此状态线程可能在Java虚拟机中运行;
- 可能在等待CPU处理器分配资源。
- 一个线程只有获取到CPU的资源后,才可以运行其
run()
方法执行代码,否则就会处于排队等待
阻塞
状态 BLOCKED该线程正在等待同步锁来进入一个同步代码块中来使用CPU资源,此时该线程就处于阻塞状态。
等待
状态 WAITING线程调用以下方法时,会自己进入等待状态:
- 不带超时的
Object类
中的wait()
方法 - 不带超时的
Thread
类中的join()
方法 LockSupport
类中的park()
方法
一直等待,直到手动唤醒
- 不带超时的
超时等待
状态 TIMED_WAITING线程调用带有正的等待时间参数的下列各方法时,会处于超时等待状态:
Object
中的wait()
Thread
中的join()
Thread
中的sleep()
LockSupport
中的parkNanos()
LockSupport
中的parkUntil()
终止
状态 TERMINATED线程执行完毕
,或run()
方法全部执行结束
后,线程进入终止状态。- 终止状态的线程
不具备继续运行
的能力。
线程状态图
- 锁池队列:当资源被一个线程访问时,上锁后,其他线程就会进入锁池队列,当锁释放后,其他线程获得了锁,就会变成可运行状态。
《Thinking in Java》
中线程被阻塞的五种可能原因:- 线程调用
sleep(ms)
,使线程睡眠,规定时间内,该线程不会运行。 - 使用
suspend()
暂停了线程的执行,除非收到resume()
消息,否则不会进入可运行状态 - 线程正在等待一些IO操作完成
- 线程试图调用另一个对象的同步方法,但那个对象处于锁状态,暂时无法使用
- 调用
wait()
暂停了线程的执行,进入了等待队列。
- 线程调用
怎么唤醒一个阻塞的线程
- 如果线程调用了
wait()、sleep()、join()
方法而导致的阻塞,可以中断线程,并抛出InterruptedException
来唤醒 - 如果该线程遇到了IO阻塞,只能等系统IO操作结束后,才能唤醒,Java代码无能为力,无法直接接触到底层操作系统的调度。
怎么检测一个线程是否持有对象监视器
- Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true
1 | public static boolean holdsLock(Object obj) |