简述java线程的生命周期 请描述线程的生命周期_并发编程

前言

一大兄弟去一家公司面试,面试官问你能简单讲下并发编程中,你用过多线程不?你能简单讲下对线程的生命周期么?
线程的生命周期?其实就这点点东西。

线程生命周期

线程的生命周期,就是指线程从创建到销毁的整个过程。就和一年的周期是春夏秋冬是一样一样的。
在线程的生命周期中,它要经过创建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5 种状态。

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。
当线程启动以后, CPU 需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。

创建状态(NEW)

当使用 new 关键字创建了一个线程之后,线程就处于创建状态,此时仅由 JVM 为其分配内存,并初始化其成员变量的值。

MyThread myThread = new MyThread();
// 线程创建状态
Thread thread = new Thread(myThread);

就绪状态(RUNNABLE)

当线程对象调用了 start()方法之后,该线程处于就绪状态。Java 虚拟机会为其创建方法调用栈和程序计数器,等待调度运行。

// 线程就绪状态
thread.start();

运行状态(RUNNING)

如果处于就绪状态的线程获得了 CPU,开始执行 run()方法的线程执行体,则该线程处于运行状态。

public class MyThread  implements Runnable {
// 线程running状态
@Override
public void run() {
System.out.println("线程运行状态(RUNNING)");
}
}

阻塞状态(BLOCKED)

阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice,暂时停止运行。
直到线程进入可运行(runnable)状态,才有机会再次获得 cpu timeslice 转到运行(running)状态。

// 线程阻塞状态
thread.sleep(300);

阻塞的情况分三种:

等待阻塞(o.wait->等待对列):

运行(running)的线程执行 o.wait()方法,JVM 会把该线程放入等待队列(waitting queue)中。

同步阻塞(lock->锁池)

运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池(lock pool)中。

其他阻塞(sleep/join)

运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法,或者发出了 I/O 请求时,JVM 会把该线程置为阻塞状态。
当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O处理完毕时,线程重新转入可运行(runnable)状态。

线程死亡状态(DEAD)

线程执行完成后,或者终止都会导致线程死亡。

// 线程死亡状态
thread.stop();

线程有三种方式结束。

  1. 线程正常结束。run()或 call()方法执行完成。
  2. 异常结束。线程抛出未捕获的异常或错误。
  3. 调用 stop方法。直接调用该线程的 stop()方法来结束该线程有可能导致死锁的情况发生,不推荐使用。