当线被创建并启动以后,它既不是一启动就进入执行状态的,也不是一直处于执行状态的,在线程的声明周期中,他要经过新建(New)、就绪(Ready)、运行(Running)、阻塞(Blocked)、和死亡(Dead)5种状态,尤其是当线程启动以后,他不可能一直霸占着CPU独自运行,所以CPU需要在多个线程之间切换,于是线程状态也会在多次运行、就绪之间转换。

新建和就绪状态

当程序创建了一个Thread对象或Thread子类的对象之后,该线程就处于新建状态,和其他的python对象一样,此时的线程对象并没有表现出任何线程的动态特征,程序也不会执行线程执行体。
当线程对象调用start() 方法时,该线程处于就绪状态,pyhton解释器会为其创建方法调用和程序计数器,处于这种状态的线程并没有开始运行,只是表示该进程可以运行了,至于该线程何时运行,取决于python解释器中线程调度器的调度。
》》》》》》》》》》》》》》》》》》》》》》》》》》
注意
启动线程使用start()方法,而不是run()方法!!!永远不要调用线程对象的run方法,调用start() 方法来启动线程,系统会把run()方法当成线程执行体来处理,但如果调用线程对象run()方法,则run()方法立即就会被执行,而且该方法返回之前其他线程无法并发执行,也就是说如果直接调用线程对象的run()方法,则系统会把线程对象当成一个普通对象,而run()方法也是一个普通方法,而不是线程执行体。另外只能对处于新建状态的线程start() 方法,也就是说,如果程序对同一个线程重调用start()方法,将引发RuntimeError异常。

运行和阻塞状态:

如果处于就绪状态的线程获得CPU,开始执行run()方法的执行体,则该线程处于运行状态,如果计算机上只有一个CPU,那么在任何时刻只有一个线程处于运行状态。当然,在一个具有多处器的机器上,将会有多个线程并行(Parallel)执行,当线程数大于处理器数时,依然会存在讴歌线程在同一个CPU上轮换的情况。
当一个线程开始运行后,他不可能一直处于运行状态(除非他的线程执行体足够短,瞬间就执行结束了),线程在运行的过程中需要被中断,目的是使其他的线程获得执行的机会,线程调度的细节取决于底层平台所采用的策略,对于采用抢占式调度策略的系统而言,系统会给每一个可执行的线程一个小的时间段来处理任务,当该时间段用完之后,系统就会剥夺该线程所占用的资源,让其他线程获得执行的机会,在选择下一个线程时,系统会考虑线程的优先级。
当发生如下情况时,线程会进入阻塞状态
1:线程调用sleep()方法主动放弃其所占用的处理器资源,
2:线程调用了一个阻塞式I/O方法,在该方法返回之前,该线程被阻塞
3:线程试图获得一个锁对象,但该锁对象正被其他线程所持有,
4:线程在等待某个通知(Notify)
针对上面几种情况,当发生如下特定的情况时可以解除阻塞,让线程重新进入就绪状态
1:调用sleep0方法的线程经过了指定时间
2:线程调用的阻塞式I/O方法已经返回
3:线程成功的获得了试图获取的锁对象
4:线程正处于等待某个通知是,其他线程发出了一个通知

线程死亡:

线程会以如下三种方式结束,结束后就进入死亡状态
1:run()方法或代表线程执行体的target函数执行完成,线程正常结束
2:线程抛出一个未捕获的Exception或者Error
注意:当主线程结束后时,其他线程不受任何影响,并不会随之结束,一旦子线程启动起来后,它就拥有和主线程相同的地位,它不会受主线程的影响。为了测试某个线程是否死亡,可以调用线程对象的 is_alive() 方法,当线程处于就绪、运行、阻塞三种状态时,该方法返回True,当线程处于新建、死亡两种状态时,该方法返回False。
另外,不要对处于死亡状态的线程调用start() 方法,程序只能对处于新建状态的线程调用start() 方法,对于处于新建状态的线程两次调用start()方法也是错误的,他们都会引起RuntimeError异常