Thread.threading

// 一个简单的倒计时例子
def countdown(n):
    while n>0:
        print('T-minus',n)
        n -= 1
        time.sleep(1)  # 休眠一秒再继续
        print(t.is_alive())  # 查询线程是否还存活

t = Thread(target=countdown,args=(10,),daemon=True)   # 创建线程
t.start()  # 启动线程
t.join()  # 加入到当前线程,等待它终止

Python解释器在所有线程都执行结束之后才继续执行代码剩余的部分,所以对于需要长时间运行的线程或者需要一直运行的后台任务,应该考虑使用后台线程。

t = Thread(target=countdown,args=(10,),daemon=True)
t.start()

后台线程无法等待,会在主线程终止时自动销毁
除了以上两个操作,没有什么其他对于线程的操作,如果需要,则需要定制。
比如:

class CountDownTask(object):
    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self,n):
        while self._running and n > 0:
            print('T-minus',n)
            n -= 1
            time.sleep(1)

c = CountDownTask()
t = Thread(target=c.run,args=(10,))
t.start()
c.terminate()  # 手动终止
t.join()  # 加入当前线程

如果遇到IO阻塞操作,那么通过轮询来终止线程将使得程序之间的协调变和非常棘手。处理这个问题,需要利用超时循环来小心操作线程
由于 GIL的原因,Python的线程被限制到同一时刻只允许一个线程执行,所以Python的线程更适用于处理IO和其他需要并发执行的阻塞操作(比如等待IO、等待从数据库获取数据等),而不是需要多处理器并行的计算型密集型任务。

判断线程状态

每个线程都是独立运行,且状态不可预测,如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就比较重要。
可以使用threading中的Event对象。Event对象包含一个可由线程设置的信号标志,允许线程等待某些事件的 发生。在初始情况下,标志为假,线程会一直阻塞直至该标志为真。一个线程如果把一个event对象的标志设置为真,那它会唤醒所有等待这个event对象的线程。如果线程等待的event对象已经是真,那它会忽略这个事件,继续执行

def countdown(n,started_evt):
    print('countdown starting')
    started_evt.set()  # 设置标志为真
    while n >0:
        print('T-minus',n)
        n -= 1
        time.sleep(1)

started_evt = Event()  # 创建一个event对象,作为启动标志
print('launching countdown')
t = Thread(target=countdown,args=(10,started_evt))  # 第二个参数是一个event对象
t.start()  # 启动线程
started_evt.wait()  # event等待线程开始
print('countdown is running')

待续…