python多线程threading详解(一)

1.简单了解下:

线程,是操作系统能够进行运算调度的最小单位。它被包含在进程之中,一个进程可以运行多个线程,线程是进程中的实际运作单位,一条线程指的是进程中的一个单一顺序的控制流。但是,python中的多线程,由于GIL(全局解释器锁)的存在,并不是真正的并行,工作模式是线程间不断的、快速的切换来完成任务,同一时间只能有一个线程工作。

2.进程和线程的关系,举个例子说明:

一个进程就像一台车,它是一个容器,有不同的功能,车本身并没有主动地做任何的事情,而线程可以理解成使用车的人,他可以踩油门,可以踩刹车,可以打方向盘,看到这里,有人可能会说,我可以一边踩油门一边打方向盘啊,同时进行,可是在python里,存在GIL,你只能在同一时间干一件事。

所以只能在IO密集型的任务中使用多线程才有意义,比如,你打开一个文件,需要2秒,你有2个文件需要打开,如果不使用多线程,你打开这2个文件,一共需要4秒,使用多线程,只需要2秒。过程如下:

线程1获取GIL的使用权,打开文件1,因为需要等待2秒,所以在等待的时候,交出了GIL的使用权;线程2,获得使用权,打开文件2,等待2秒,因为在这个切换中非常快,感受不到这种切换,觉得是同时打开了2个文件,共耗时2秒。

实现多线程的方式有2种,一种是使用调用threading模块的Thread, 一种是通过构建多线程类(继承Thread)来实现。

方法一,调用Thread来实现多线程。

1.demo 1

import time
from threading import Thread, current_thread


def demo():
    print(f'子线程开始, 线程名字: {current_thread().name}')
    time.sleep(2)  # 模拟等待操作, 模拟耗时的io任务
    # current_thread函数, 返回当前线程对象, 调用name方法输出当前线程名
    print(f'子线程结束, 线程名字: {current_thread().name}')


if __name__ == '__main__':
    print('主线程开始...')
    threads = [Thread(target=demo) for _ in range(3)]  # 这里是创建3个线程,放到一个列表里
    for t in threads:
        t.start()  # 启动线程
    for t in threads:
        t.join()  # 线程等待
    print('主线程结束...')

输出如下:

python多线程threading详解(一)_第1张图片

这里解释下, t.start()是启动线的方法, t.join()是线程等待的意思(阻塞调用这个方法的线程(主线程是调用子线程的方法)),在这里用t.join(),主线程会等所有的子线程完成后再结束,因为每一个子线程都启用了t.join();

疑问一:t.join()可以跟t.start()放在同一循环内吗?

python多线程threading详解(一)_第2张图片

答案是不可以,如果放在一个循环里,每启动一个子线程t.start后,就马上做t.join,这个时候,启动的这个子线程是强占资源的,抢到这个资源后,必须要等启动的这个子线程完成后,才能启动下一个子线程,

也就是说,这个处理是阻塞的,没有起到多线程的效果,是线性运行的。效果如下

python多线程threading详解(一)_第3张图片

 疑问二:如果不使用join可以吗?

python多线程threading详解(一)_第4张图片

 答案是可以的,但是,在实际使用中不会这样用,主线程结束后,子线程就是放养状态,不知道什么时候才结束掉,不方便管理。

 效果如下:

python多线程threading详解(一)_第5张图片

 另外,join可以设置等待时间,使用参数timeout,timeout设置的时间到了后,主线程得到使用权,主线程结束。

python多线程threading详解(一)_第6张图片

 方法二,继承Thread来实现多线程。其实就是重写Thread里面的run方法来实现多线程

# _*_ coding: utf-8 _*_

import time
from threading import Thread, current_thread


class Demo(Thread):

    def run(self):
        print(f'子线程{self.name}开始...')  # 继承Thread后, 可以调Thread的方法name来获取当前线程名字
        time.sleep(2)
        print(f'子线程{self.name}结束...')


if __name__ == '__main__':
    print('主线程开始...')
    threads = [Demo() for _ in range(3)]  # 创建3个线程对象
    for t in threads:
        t.start()

    for t in threads:
        t.join()

    print('主线程结束...')

你可能感兴趣的:(python,python,开发语言)