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

python线程的多任务编程

程序员文章站 2023-11-29 11:31:34
线程多任务多任务介绍多任务理解多任务的实现方式线程线程介绍线程的使用使用join()方法的使用setDaemon()方法的使用enumerate()的使用,查看线程数量子线程的创建与执行继承Thread类创建线程多线程共享全局变量线程的传参线程的资源抢占多任务多任务介绍对于人来说,一边听歌,一遍跳舞就是多任务。对于电脑,简单的说,同一时间执行多个程序处理数据叫做多任务多任务理解单核CPU单核cpu在处理多任务的时候是根据时间片轮转的方式进行的,比如执行QQ1us,然后切换微信执行1us,最后...

多任务

多任务介绍

对于人来说,一边听歌,一边跳舞就是多任务。
对于电脑,简单的说,同一时间执行多个程序处理数据叫做多任务

多任务理解

单核CPU
python线程的多任务编程
单核cpu在处理多任务的时候是根据时间片轮转的方式进行的,比如执行QQ1us,然后切换微信执行1us,最后是执行钉钉1us,如此循环。因为cpu的切换速度过快,导致我们认为三个软件是同时执行的

多核cpu
python线程的多任务编程
并发:当cpu不能同时执行当前所有任务时,就会循环执行,是假的多任务
并行:当cpu可以同时执行当前所有任务时,是真的多任务

多任务的实现方式

实现多任务有三种方式:

  • 线程
  • 进程
  • 协程

线程

线程介绍

线程是指在一个单独进程中,对于CPU和内存而言的多个工作单位,所有线程在进程中的资源都是共享的,包括全局数据、执行代码等。

线程的使用

  • 先介绍三个方法
    • setDaemon(True): 主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出.
    • join(): 主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行
    • enumerate(): 查看线程数量

使用

  • 代码示例
    import threading
    import datetime
    
    
    def A():
        print('函数A')
        print(datetime.datetime.now())
    
    
    def B():
        print('函数B')
        print(datetime.datetime.now())
    
    
    if __name__ == '__main__':
        # 指定线程到A()和B()函数里执行
        t1 = threading.Thread(target=A)
        t2 = threading.Thread(target=B)
        # 执行线程
        t1.start()
        t2.start()
        print('--end--')
    
    

从输出结果可以知道,两个线程是在同一时间一起执行的。不过因为抢占式的特点,最后一条语句print('--end--')有时会在子线程的前面执行。

join()方法的使用

如果我们想让print('--end--')在最后执行,可以用到join()方法,当子线程结束后,主线程才会结束。

  • join方法的使用,代码示例
import threading
import datetime


def A():
    print('函数A')
    print(datetime.datetime.now())


def B():
    print('函数B')
    print(datetime.datetime.now())


if __name__ == '__main__':
    # 指定线程到A()和B()函数里执行
    t1 = threading.Thread(target=A)
    t2 = threading.Thread(target=B)
    # 执行线程
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print('--end--')

setDaemon()方法的使用

如果不想让主线程等待子线程完成后才结束,可以使用setDaemon

  • 代码示例
    import threading
    import time
    
    
    def A():
        for i in range(3):
            print("A")
            time.sleep(1)
    
    
    if __name__ == '__main__':
        t1 = threading.Thread(target=A)
        t1.setDaemon(True)  # 要放在线程开始之前
        t1.start()
    
    

enumerate()的使用,查看线程数量

  • 代码示例
    import threading
    import datetime
    
    
    def A():
        print('函数A')
        print(datetime.datetime.now())
    
    
    def B():
        print('函数B')
        print(datetime.datetime.now())
    
    
    if __name__ == '__main__':
        # 创建两个主线程,指定线程到A()和B()函数里执行
        t1 = threading.Thread(target=A)
        t2 = threading.Thread(target=B)
        # 执行线程
        t1.start()
        t2.start()
        print(threading.enumerate())
        print('--end--')
    
    

子线程的创建与执行

当我们调用start()方法时,子线程才会被创建,并且执行

继承Thread类创建线程

我们可以通过修改Thread类的run()方法里的代码,来完成重写run()方法

  • 代码示例
    import threading
    
    
    class T(threading.Thread):
        def run(self):
            self.a()
    
        def a(self):
            for i in range(3):
                print('a')
    
    
    if __name__ == '__main__':
        t1 = T()
        t1.start()  # 当调用start()方法时,会主动调用run()方法
    
    

当我们调用start()方法时,会主动调用run()方法

多线程共享全局变量

  • 代码示例
    import threading
    
    
    def a():
        global num
        num += 1
        print(f'a:{num}')
    
    
    def b():
        print(f'b:{num}')
    
    
    if __name__ == '__main__':
        num = 10
        print(num)
        t1 = threading.Thread(target=a)
        t2 = threading.Thread(target=b)
        t1.start()
        t2.start()
        print(num)
    
    

线程的传参

当用线程去函数里执行代码时,我们可以看到函数后边是没有括号()的,所以涉及到传参的时候我们该怎么解决这个问题?

  • 解决方法
    • 我们可以使用args参数进行传参,参数为元组
    • 当我们想要传入字典时,可以使用kwargs进行传入
  • 代码示例
    import threading
    
    
    def a(x):
        print(x)
    
    
    def b(**kwargs):
        print(kwargs)
    
    
    if __name__ == '__main__':
        num = 1
        # 使用args参数进行传参
        t1 = threading.Thread(target=a, args=(num,))
        # 使用kwargs参数进行传入字典
        t2 = threading.Thread(target=b, kwargs={"A": 1})
        t1.start()
        t2.start()
    

线程的资源抢占

  • 代码示例
    import threading
    
    
    def a(x):
        global num
        for i in range(x):
            num += 1
        print(f'a: {num}')
    
    
    def b(x):
        global num
        for i in range(x):
            num += 1
        print(f'b: {num}')
    
    
    if __name__ == '__main__':
        num = 100
        t1 = threading.Thread(target=a, args=(1000000, ))
        t2 = threading.Thread(target=b, args=(1000000, ))
        t1.start()
        t2.start()
        print(num)
    
    

运行结果
python线程的多任务编程
正常的结果应该是2000100,但是因为资源抢占导致数据不正确,使用就可以避免这个问题,下篇博客我会细讲怎么解决这个问题。

最后,有喜欢博主写的内容的伙伴可以点赞收藏加关注哦!

本文地址:https://blog.csdn.net/weixin_44604586/article/details/107091271