线程的生命周期
线程的生命周期是线程对象的生老病死,即线程的状态。
线程生命周期可以通过 getState() 方法获得,线程的状态是 Thread.State 枚举类型定义的。有以下几种:
新建状态(New)。创建了线程对象,在调用 start() 启动之前的状态;此时仅仅由JVM为其分配内存,并初始化成员变量的值。此时仅仅是个对象。
就绪状态(Runnable)。就是调用线程的 start() 方法后,该线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;该线程进入就绪状态,JAVA虚拟机会为其创建方法调用栈和程序计数器。线程的执行是由底层平台控制, 具有一定的随机性。
运行状态(Running)。当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能;(当处于就绪状态的线程获得CPU,它就会执行 run() 方法)
对于一个单核cpu(或者是一个内核)来说,只能同时执行一条指令,而JVM通过快速切换线程执行指令来达到多线程的,真正处理器就能同时处理一条指令,只是这种切换速度很快,我们根本不会感到。为了线程切换后能恢复到正确的执行位置,每条线程都有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。当一个线程开始运行后,它不可能一直持有CPU(除非该线程执行体非常短,瞬间就执行结束了)。所以,线程在执行过程中需要被中断,目的是让其它线程获得执行的CPU的机会。线程的调度细节取决于底层平台所采用的策略。
阻塞状态(Blocked)。在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态。原因如下:
- 等待 I/O 流的输入输出
- 等待网络资源,即网速问题
- 调用 sleep() 方法,需要等sleep时间结束
- 调用 wait() 方法,需要调用 notify() 唤醒线程
- 其他线程执行 join() 方法,当前线程则会阻塞,需要等其他线程执行完。
死亡状态(Terminated)。
- run() / call() 方法执行完成,线程正常结束;
- 线程抛出一个未捕获的 Exception 或 Error;
- 直接调用线程的 stop() 方法结束该线程——该方法容易导致死锁,通常不建议使用。