从操作系统层面来描述:
- 1、初始状态 仅在语言层面创建了线程对象,还未与操作系统线程关联
- 2、可运行状态 就绪状态,指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行
- 3、运行状态 指获取了CPU时间片运行中的状态,当CPU时间片用完,会从运行状态切换至可运行状态,会导致线程上下文切换
- 4、阻塞状态 如果调用了阻塞API,如BIO读写文件,这是线程实际不会用到CPU,会导致线程上下文切换,进入阻塞状态 等BIO操作执行完毕,会由操作系统唤醒阻塞的线程,切换至可运行状态 与可运行状态的区别是,对阻塞状态的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们
- 5、终止状态 表示线程已经执行完毕,生命周期已经结束,不会再转换为其他状态
从Java API层面描述的,Thread类中的State枚举定义的六种状态:
- NEW 线程刚被创建,但是还没有调用start()方法 同五种状态中的 初始状态是一致的
- RUNNABLE 当调用了start()方法之后,注意Java API层面的RUNNABLE状态涵盖了操作系统层面 可运行状态、运行状态和阻塞状态(操作系统层面)(由于BIO导致的线程阻塞,在Java里无法区分,仍然认为是可运行状态)
- BLOCKED 等待获取锁
- WAITING join
- TIMED_WAITING sleep(1000)
- TERMINATED 线程执行完毕进入终止状态 与操作系统中的终止状态一致
状态转换图中的编号:
- 调用线程对象的start()方法,将Java的线程关联到操作系统的线程,变为RUNNABLE
- 线程使用synchronizd(obj)获取到对象锁之后,调用obj.wait() 线程从RUNNANLE 变为 WAITING,当调用obj.notify(),obj.notifyAll(),t.interrupt()时,如果竞争锁成功,t线程从 WAITING变为 RUNNABLE。如果获取锁失败,t线程从WAITING变为BLOCKED
- 当前线程调用t.join()方法时,当前线程从RUNNABLE状态变为WAITING 注意是当前线程在t线程对象的监视器上等待。t线程运行结束,或调用了当前线程的interrupt()时,当前线程从WAITING变为RUNNABLE状态
- 当线程调用LockSupport.park()方法会让当前线程从RUNNABLE变为WAITING,调用LockSupport.unpark(目标线程)或调用线程的interrupt(),会让目标线程从WAITING变为RUNNABLE
- 线程使用synchronized(obj)获取对象锁后,调用obj.wait(long n)方法,线程从RUNNABLE变为TIMED_WAITING状态,线程等待时间超过了n毫秒,或者调用了obj.notify(),obj.notifyAll(),t.interrupt()时,如果竞争锁成功 线程从TIMED_WAITING变为RUNNABLE,如果竞争锁失败,从TIMED_WAITING变为BLOCKED状态
- 当线程调用t.join(long n)方法时,当前线程从RUNNABLE变为TIMED_WAITING,注意是当前线程在t线程对象的监视器上等待。当前线程等待时间超过了n毫秒,或t线程运行结束,或者调用了当前线程的interrupt()时,当前线程从TIMED_WAITING变为RUNNABLE
- 当前线程调用Thread.sleep(long n) 当前线程从RUNNABLE状态变为TIMED_WAITING状态,当前线程等待时间超过了n毫秒,当前线程从TIMED_WAITING变为RUNNABLE
- LockSupport.parkNanos(long nanos)或LockSupport.parkUntil(long deadline)时,当前线程从RUNNABLE变为TIMED_WAITING状态,调用LockSupport.unpark(目标线程)或调用线程的interrupt,或者等待超时,会让目标线程从TIMED_WAITING变为RUNNABLE
- 当线程用synchronized(obj)获取锁时如果竞争失败,从RUNNABLE变成BLOCKED,当持有锁的线程代码执行完毕会唤醒该对象上所有BLOCKED的线程重新竞争锁,如果线程竞争成功,从BLOCKED变为RUNNABLE,其他失败的线程仍然BLOCKED
- 当前线程所有代码运行完毕,进入TERMINATED