1.概念引入
当线程被创建并启动以后,它既不是一启动就进入执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)五种状态。
注意:理解其生命周期需要结合多线程所运行的并发机制来执行,一方面我们需要理解其生命周期的执行方式以及存在意义,同时也要学会它的语法。
2.新建状态
(1)new成功创建线程,未调用start()方法
当程序使用new关键字创建一个线程后,该线程就处于新建状态,但是还没有在该线程.上调用start()方法之前的状态。它是一个活的Thread对象,有JVM为其分配内存初始化其成员变量,没有任何的动态特征,不是一一个执行线程。这时,我们把该线程看做不是活的。
(2)关键
此刻该线程仅被分配内存并被初始化成员变量。
3.就绪状态(可运行状态)
(1)等待JVM调度
当线程对象调用了start()方法之后,该线程就处于就绪状态,JVM为其创建方法调用栈和程序计数器。但可能依然没有开始运行,运行由JVM里线程调度器的调度。在线程运行之后或者从阻塞、等待或者睡眠状态回来之后,它可能返回就绪状态。当线程处于就绪状态时,它被视为活的。
(2)理解
如果说新建状态是在为其准备资源,则就绪状态则可以理解成是加入可运行池,此刻众多线程都在仰望JVM,渴望得到其的青睐!
4.运行状态
(1)唯一的进入方法
这是当线程调度程序(从可运行池中)选择一个线程作为当前执行进程时该线程所处的状态。一个线程转出运行状态有几种原因。但是只有一种方法进入运行状态:调度程序从可运行池选择一个线程。
(2)
假设在单处理机的限制下,执行的是并发机制,这意味着在每个时刻实际上只有一个线程处于运行状态,此刻只有一位是天选之子。
5.阻塞状态
5.1 进入阻塞状态
(1)线程调用了sleep方法主动放弃所占有的资源线程
(2)调用了一个阻塞式IO方法,在该方法返回的时候被阻塞
(3)线程尝试获取一个同步监听器,但是被其他线程占有
(4)在等待某个通知
(5)调用线程suspend方法挂起,不推荐使用容易造成死锁
5.2 转进就绪状态
进入阻塞状态的线程在获得执行机会后重新进入就绪状态,而不是运行状态。必须等待线程调度器的再次调用才运行。
下面情况进入就绪状态:
(1)调用sleep方法的线程经过了指定时间
(2)线程调用的阻塞式I0方法已经返回
(3)线程成功获取试图取得同步监听器
(4)线程在等待某个通知,其他线程发出一个通知
(5)处于挂起状态的线程调用了resume恢复方法
(6)有一个方法例外,调用yield方法可以让处于运行状态的线程转入就绪状态。
6.线程死亡
5.1 结束方式
线程会以下三种方式之一结束,结束后就处于死亡状态:
(1)run()方法执行完成,线程正常结束。
说明:一个开启的多线程,最终走到的话是run()方法这一步
(2)线程抛出一个未捕获的异常或者错误。
(3)直接调用该线程的stop方法来结束该线程,该方法容易导致死锁,通常不推荐。
5.2 死亡特点
(1)线程死亡它可能仍然是一个活的Thread对象,但是不是一个单独的执行线程。
(2)当主线程结束的时候,其他线程不受影响。一旦子线程启动它就拥有和主线程一样的地位。
(3)一旦一个线程死去,它就不能复生。对一个已经死亡的线程调用start()方法使它重新启动,会抛出llegalThreadState Exception异常。
5.3 isAlive()测试
为了测试某条线程是否已经死亡,可以调用线程对象的isAlive()方法,当线程处于就绪,运行和阻塞三种状态时,该方法将返回true;当线程处于新建、死亡两种状态时,该方法返回false。不要试图对一个已经死亡的线程调用start()方法使它重新启动,会抛出llegalThreadStateException异常。
理解:是否还占有系统资源。
7.线程状态转换
核心:阻塞状态,运行状态,就绪状态间的相互转换