目录
状态解释
状态间的转化
状态解释
状态间的转化
- 根据Thread类中定义的枚举类型State值,可以看出有6种状态:
- 可以通过 Thread.getState 方法获得线程的状态
- NEW(新建)New:
- 新建了Thread类对象,但是没有启动的线程
- 尚未启动;已创建但是还没有启动的线程,比如new Thread后的线程,但是还没执行start方法
- RUNNABLE(可运行状态,而不只是正在运行的)Runnable:
- 正在 JVM 中运行;或者正在等待操作系统的其他资源(比如处理器)
- new后的线程,调用了start方法,此时的线程就是Runnable状态
- 有些编程语言会把RUNNABLE分成2种情况:1-running和2-ready
- 也就是处于此状态的线程有可能正在执行,也有可能正在等待着CPU为它分配执行时间(该线程已经获取了除CPU资源外的其他资源,等待获取CPU 资源后才会真正处于运行状态)
- 以上2种在Java中都属于Runnable
- 调用了start方法,不代表线程启动了,有可能还在队列中等待资源分配,还没被处理器执行
- 拿到CPU运行后,同样也叫做Runnable状态
- 运行时的线程,CPU资源被抢走了,此时线程还是处于Runnable状态,因为只要得到CPU,它就可以继续运行
- Runnable既可以代表可运行的,也可以代表运行中的
- BLOCKED(被阻塞) Blocked:
- 正在等待监视器锁(内部锁)的释放
- 当一个线程进入到被synchronized修饰的代码块时,而且该锁被其他线程拿走了,那么这个线程的状态就是Blocked
- 一定是进入了被Synchronized保护的代码
- 比如线程A进入了一个synchronized方法,线程B也想进入这个方法
- 但是这个方法的锁已经被线程A获取了,这个时候线程B就处于BLOCKED状态
- WAITING(无限期等待) Waiting:
- 处于waiting状态的线程会等待另外一个线程处理特殊的行为
- 举个例子,如果一个线程调用了wait方法(并且没有使用timeout参数),那么这个线程就会处于waiting状态直到另外一个线程调用这个对象的notify或者notifyAll方法后才会解除这个状态
- 线程调用以下方法会处于无限期等待状态:
- 1-没有设置Timeout参数的 Object.wait()方法
- 2-没有设置Timeout参数的 Thread.join()方法
- 3-LockSupport.park()方法
- Object.wait(),Thread.join(),LockSupport.park()方法会让线程从Runnable进入Waiting状态
- 注意这里的方法不带参数,等待没有时间限制
- 会一直等待,直到手动唤醒
- 唤醒信号:Object.notify(),Object.notifyAll(),LockSupport.unpark()会让线程从Waiting唤醒,回到Runnable状态
- TIMED_WAITING(限期等待) Timed Waiting:
- 无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒
- 等待时间内,也可以被唤醒信号唤醒
- 线程调用带有正的等待时间参数的下列各方法时,会处于定时等待状态:
- 1-Thread.sleep(long millis)方法,常常用“使一个线程睡眠”进行描述
- 2-设置了Timeout参数的 Object.wait()方法,常常用“挂起一个线程”进行描述
- 3-设置了Timeout参数的 Thread.join()方法
- 4-LockSupport.parkNanos()方法(带有时间)
- 5-LockSupport.parkUntil()方法(带有时间)
- 一般来说,把Blocked(被阻塞)、Waiting(无限期等待)、Timed_Waiting(限期等待)都称为阻塞状态,不仅仅是Blocked
- 睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态
- 阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁
- 而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入
- TERMINATED(终止状态) Terminated:
- 已经执行完毕,已终止线程的线程状态,线程已经结束执行
- 可以是线程结束任务之后自己结束,或者因产生了异常而结束
- 上述6种状态在遇到特定事件发生的时候将会互相转换,它们的转换关系如下图:
- 上图状态的转换和方法已经很清晰了
- 锁池队列:当资源被一个线程访问时,上锁后,其他线程就会进入锁池队列,当锁释放后,其他线程获得了锁,就会变成可运行状态
《Thinking in Java》
中线程被阻塞的五种可能原因:- 线程调用
sleep(ms)
,使线程睡眠,规定时间内,该线程不会运行 - 使用
suspend()
暂停了线程的执行,除非收到resume()
消息,否则不会进入可运行状态 - 线程正在等待一些IO操作完成
- 线程试图调用另一个对象的同步方法,但那个对象处于锁状态,暂时无法使用
- 调用
wait()
暂停了线程的执行,进入了等待队列
- 线程调用