当前位置 > it书童 > 知识体系 > 正文
推荐小册
java高效编程
怎样更高效地用 java 编程

juc并发工具库
java并发编程工具库

设计模式
设计模式

jvm调优
jvm调优

rabbitmq实战
rabbitmq实战

redis实战
redis实战

Keepavlied高可用集群
Keepavlied高可用集群

nginx入门到实战
nginx入门到实战

java调试
java调试中遇到的各种坑

java输入输出流
java输入输出流

线程的生命周期

知识体系 it书童 2019-10-03 22:07:52 0赞 0踩 653阅读 0评论

线程的生命周期包括五种状态:

  • 新建 New

  • 就绪 Ready

  • 运行 Running

  • 阻塞 Blocked

  • 死亡 Dead

新建和就绪状态

当程序创建了一个 Thread 对象后,该线程就处于新建状态,此时并没有表现出任何线程的动态特征,程序也不会执行线程执行体

当线程对象调用 start() 方法后,就处于就绪状态,表示可以运行了,何时运行要取决于 Python 解释器中线程调度器的调度

启动线程使用 start(),而不是 run(), 永远不要调用线程对象的 run(), 因为 run() 会立即执行,且在该方法返回之前其他线程无法并发执行

invoke_run.py

import threading


def action(max):
    for i in range(max):
        # 直接调用 run() 方法时,Thread 的 name 属性返回的是该对象的名字
        # 而不是当前线程的名字
        # 使用 threading.current_thread().name 总是获取当前线程的名字
        print(threading.current_thread().name + " " + str(i))


for i in range(5):
    print(threading.current_thread().name + " " + str(i))
    if i == 2:
        # 直接调用线程对象的 run()
        # 系统会把线程对象当成普通对象,把 run() 当成普通方法
        # 所以下面两行代码并不会启动两个线程,而是依次执行两个 run()
        threading.Thread(target=action, args=(5,)).run()
        threading.Thread(target=action, args=(5,)).run()

$ python invoke_run.py
MainThread 0
MainThread 1
MainThread 2
MainThread 0
MainThread 1
MainThread 2
MainThread 3
MainThread 4
MainThread 0
MainThread 1
MainThread 2
MainThread 3
MainThread 4
MainThread 3
MainThread 4

只能对处于新建状态的线程调用 start(), 如果对同一线程重复调用,会引发 RuntimeError 异常

运行和阻塞状态

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

线程在运行过程中需要被中断,使其他线程获得执行的机会

当发生以下情况下,线程进入阻塞状态:

  • 线程调用 sleep() 方法主动放弃其所占用的处理器资源

  • 线程调用了一个阻塞式 I/O 方法,在该方法返回之前,该线程被阻塞

  • 线程试图获得一个锁对象,但该锁对象正被其他线程所持有

  • 线程在等待某个通知

当前正在执行的线程被阻塞后,其他线程就获得执行的机会。被阻塞的线程会在合适的时候重新进入就绪状态

以下情况,线程可解除阻塞,重新进入就绪状态:

  • 调用 sleep() 方法的线程过了指定时间

  • 线程调用的阻塞式 I/O 已经返回

  • 成功获得锁对象

  • 线程正在等待某个通知时,其他线程发出了一个通知

线程死亡

  • run() 或代表线程执行体的 target 函数执行完成,线程正常结束

  • 线程抛出一个未捕获的 Exception 或 Error

当主线程结束时,其他线程不受任何影响,并不会随之结束

不要试图对一个已经死亡的线程调用 start(),挂了就是挂了,不可能重生

start_dead.py

import threading


def action(max):
    for i in range(max):
        print(threading.current_thread().name + " " + str(i))


sd = threading.Thread(target=action, args=(5,))
for i in range(5):
    print(threading.current_thread().name + " " + str(i))
    if i == 2:
        sd.start()
        print(sd.is_alive())
    if i > 2 and not(sd.is_alive()):
        # i > 2 说明线程启动过了,如果线程处于死亡状态,试图激活
        print(sd.is_alive())
        sd.start()

$ python start_dead.py
MainThread 0
MainThread 1
MainThread 2
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
False
MainThread 3
False
Traceback (most recent call last):
  File "start_dead.py", line 18, in <module>
    sd.start()
  File "/Users/airmb/.pyenv/versions/3.6.6/lib/python3.6/threading.py", line 842, in start
    raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
关于我
一个文科出身的程序员,追求做个有趣的人,传播有价值的知识,微信公众号主要分享读书思考心得,不会有代码类文章,非程序员的同学请放心订阅
转载须注明出处:https://www.itshutong.com/articles/24/thread-life-cycle