1.生命周期
一个线程从创建,到最终的消亡,需要经历多种不同的状态,而这些不同的线程状态,由始至终也构成了线程生命周期的不同阶段。线程的生命周期可以总结为下图。
其中,几个重要的状态如下所示。
NEW:初始状态,线程被构建,但是还没有调用start()方法。
RUNNABLE:可运行状态,可运行状态可以包括:运行中状态和就绪状态。
BLOCKED:阻塞状态,处于这个状态的线程需要等待其他线程释放锁或者等待进入synchronized。
WAITING:表示等待状态,处于该状态的线程需要等待其他线程对其进行通知或中断等操作,进而进入下一个状态。
TIME_WAITING:超时等待状态。可以在一定的时间自行返回。
TERMINATED:终止状态,当前线程执行完毕。
2.代码示例
为了更好的理解线程的生命周期,以及生命周期中的各个状态,接下来使用代码示例来输出线程的每个状态信息。
WaitingTime
创建WaitingTime类,在while(true)循环中调用TimeUnit.SECONDS.sleep(long)方法来验证线程的TIMED_WARTING状态,代码如下所示。
WaitingState
创建WaitingState类,此线程会在一个while(true)循环中,获取当前类Class对象的synchronized锁,也就是说,这个类无论创建多少个实例,synchronized锁都是同一个,并且线程会处于等待状态。接下来,在synchronized中使用当前类的Class对象的wait()方法,来验证线程的WAITING状态,代码如下所示。
BlockedThread
BlockedThread主要是在synchronized代码块中的while(true)循环中调用TimeUnit.SECONDS.sleep(long)方法来验证线程的BLOCKED状态。当启动两个BlockedThread线程时,首先启动的线程会处于TIMED_WAITING状态,后启动的线程会处于BLOCKED状态。代码如下所示。
ThreadState
启动各个线程,验证各个线程输出的状态,代码如下所示
运行ThreadState类,如下所示。
可以看到,未输出任何结果信息。可以在命令行输入“jps”命令来查看运行的Java进程。
可以看到ThreadSate进程的进程号为1156,接下来,输入“jstack 1156”来查看ThreadSate进程栈的信息,如下所示。
由以上输出的信息可以看出:名称为WaitingTimeThread的线程处于TIMED_WAITING状态;名称为WaitingStateThread的线程处于WAITING状态;名称为BlockedThread-01的线程处于TIMED_WAITING状态;名称为BlockedThread-02的线程处于BLOCKED状态。
注意:使用jps结合jstack命令可以分析线上生产环境的Java进程的异常信息。
也可以直接点击IDEA下图所示的图表直接打印出线程的堆栈信息。
输出的结果信息与使用“jstack 进程号”命令输出的信息基本一致。