# 概述及创建线程

# threading

  • Python早期利用thread模块(现更名为_thread)来实现多线程,但过于底层,故现在多使用threading模块。

  • 虽然线程的数量可以自己定义,但是线程数并不是越多越好,因为线程的创建、维护和删除也会有一定的开销。所以如果设置的很大,反而可能会导致速度变慢。

  • 线程间共享进程的内存空间-因此利用全局变量的形式实现线程间通信是可行的

    • 线程对全局变量的随意是修改可能造成多线程之间对全局变量的混乱,即线程非安全
  • Thread类可以创建线程,调用其start​方法开始执行

    • 创建的线程会在主线程结束时自动销毁,因此一般需要使用join([timeout])​表示让当前线程(一般是主线程)等待调用join​的子线程执行完毕再继续执行下去,如果传入timeout​则表示最长等待时间。
    • 对于后台线程(设置了daemon=True​)是无法等待的,因此会在主线程终止时自动销毁。
  • Lock为临界资源加锁

    • 多个进程竞争使用同一个资源时需要加上保护(“锁”),否则资源会处于“混乱”的状态-100个线程同时向一个全局变量做加1的操作,最后结果远小于100。
  • Queue解决进程间通信

极简示例:

# Code to execute in an independent thread
import time
def countdown(n):
    while n > 0:
        print('T-minus', n)
        n -= 1
        time.sleep(5)

# Create and launch a thread
from threading import Thread
t = Thread(target=countdown, args=(10,))
t.start()

# Thread类创建线程

可以通过Thread类创建一个线程,有两种方式-从target传入一个callable​对象或者重写其子类的run​方法。

当线程对象被调用start​方法时,线程就会开始执行。

from random import randint
from threading import Thread
from time import time, sleep


class DownloadTask(Thread):

    def __init__(self, filename):
        super().__init__()
        self._filename = filename

    def run(self):
        print('开始下载%s...' % self._filename)
        time_to_download = randint(5, 10)
        sleep(time_to_download)
        print('%s下载完成! 耗费了%d秒' % (self._filename, time_to_download))


def main():
    start = time()
    t1 = DownloadTask('Python从入门到住院.pdf')
    t1.start()
    t2 = DownloadTask('Peking Hot.avi')
    t2.start()
    t1.join()
    t2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()

# 获取线程唯一标识

thread_id = threading.get_ident()