欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python 多线程学习六 一文了解多线程

程序员文章站 2022-07-03 17:56:13
python 多线程学习六 demo_00x00 threading模块的两个函数1、start()2、join()0x01 单线程执行demo0x00 threading模块的两个函数1、start()该模块,顾名思义就是开始的意思,就是开启线程。2、join()join阻塞调用它的线程,直到等待被调用的线程运行结束,其实就变成了单线程。参数timeout的作用是,当前线程等待被调用的子线程的时间,如果时间到了,不管子线程是否结束,当前线程都进入就绪状态,重新等待CPU调度。0x01 单线程...

0x00 三个函数

1、start()

该模块,顾名思义就是开始的意思,就是开启线程。

2、join()

join阻塞调用它的线程,直到等待被调用的线程运行结束,其实就变成了单线程。参数timeout的作用是,当前线程等待被调用的子线程的时间,如果时间到了,不管子线程是否结束,当前线程都进入就绪状态,重新等待CPU调度。

3、setDaemon()

当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就*停止。

0x01 单线程执行demo

1、准备,定义一个方法

def hello(people):
    sleep(1)
    print(f"hello:\t{people}")
    print(f"cunrent_threading_name:\t{threading.current_thread().getName()}")
    sleep(1)

该方法的执行,首先,休眠1秒–>打印hello–>打印当前线程名–>休眠一秒

2、首先、不使用线程,直接调用

from threading import Thread
import threading
from time import sleep
import os
import sys
import time
def hello(people):
    sleep(1)
    print(f"hello:\t{people}")
    print(f"cunrent_threading_name:\t{threading.current_thread().getName()}")
    sleep(1)
if __name__ == '__main__':
    peoples = ['people1','people2','people3','people4','people5','people6','people7','people8']
    t1 = time.time()
    for i in peoples:
        hello(i)
    t2 = time.time()
    print(f"time running:\t{round(t2-t1,3)}")

程序的执行:由for循环,顺序调用hello()方法,所以每调用一次执行两次sleep(1)函数,即休眠两秒,共计休眠16.007秒,从运行的结果来看,每次调用hello()方法的都是主线程,并没有穿件子线程。

python 多线程学习六  一文了解多线程

3、使用子线程,不分配线程个数,直接调用,这时我们注意join()函数

if __name__ == '__main__':
    peoples = ['people1','people2','people3','people4','people5','people6','people7','people8']
    t1 = time.time()
    for people in peoples:
        t = Thread(target=hello,args=(people,))
        t.setDaemon(True)
        t.start()
        t.join()
    t2 = time.time()
    print(f"time running:\t{round(t2-t1,3)}")

运行结果,我们可以看到for循环,没运行一次创建一个子线程,每次调用hello()方法都会创建一个子线程,运行总耗时为16.014秒,会发现它比直接调用耗时还要多一点,这时因为时间上每次都是创建单个线程,join()方法将上一个子线程阻塞,使得每个子线程顺序的运行都必须依靠上一个子线程的运行结束才会运行,所有子线程运行完毕,主线程结束。
python 多线程学习六  一文了解多线程

0x02 守护线程

我们把3中的join()方法注释掉,不对线程进行阻塞,但设置守护线程:

if __name__ == '__main__':
    peoples = ['people1','people2','people3','people4','people5','people6','people7','people8']
    t1 = time.time()
    for people in peoples:
        t = Thread(target=hello,args=(people,))
        t.setDaemon(True)
        t.start()
        # t.join()
    t2 = time.time()
    print(f"time running:\t{round(t2-t1,3)}")

python 多线程学习六  一文了解多线程
我们发现,设置了守护线程,但不适用join()进行阻塞,程序运行完毕,虽然子线程没有运行,整个程序由于主线程的终止而终止,程序不会报错

0x03 不设置守护线程、不使用join()阻塞

python 多线程学习六  一文了解多线程我们发现程序的执行不在想之前那样顺序执行,这是因为没有join()方法,没有对线程的运行进行阻塞,此时所有子线程同步执行,由于没有设置守护线程,我们发现此时主线程已经结束,从这里我们也可以看到:join()方法是控制线程执行同步的。

0x04 多线程同步执行

我们,设置适用两个线程,为了控制方便我们适用队列:队列的maxsize设置为2

from threading import Thread
import threading
from time import sleep
import os
import sys
import time
from queue import Queue
def hello(people):
    sleep(1)
    print(f"hello:\t{people}")
    print(f"cunrent_threading_name:\t{threading.current_thread().getName()}")
    sleep(1)
if __name__ == '__main__':
    peoples = ['people1','people2','people3','people4','people5','people6','people7','people8']
    q = Queue(maxsize=2)
    t1 = time.time()
    for people in peoples:
        t = Thread(target=hello,args=(people,))
        t.setDaemon(True)
        q.put(t)
        if (q.full() == True):
            thread_list = []
            while q.empty() == False:
                t = q.get()
                thread_list.append(t)
                t.start()
            for t in thread_list:
                t.join()
                print("*"*50)
    t2 = time.time()
    print(f"time running:\t{round(t2-t1,3)}")

python 多线程学习六  一文了解多线程
我们发现for,循环没两个值被分配到一组,由于队列的长度为2,每组的两个子线程同步执行,组之间的线程由于join阻塞同步执行,从执行时间来看,约为不适用多线程的一半。
参考:

本文地址:https://blog.csdn.net/weixin_40950781/article/details/107294067