• 第八章 多线程和线程池编程


    1. 并发和并行

    在这里插入图片描述

    2. 多线程编程

    2.1 实例化Tread类

    2.1.1 基础编程

    import time
    from threading import Thread
    
    
    def sleep_task(sleep_time):
        print("sleep {} seconds start!".format(sleep_time))
        time.sleep(sleep_time)
        print("sleep {} seconds end!".format(sleep_time))
    
    
    if __name__=="__main__":
        srat_time=time.time()
        t1=Thread(target=sleep_task,args=(2,))
        t1.start()
    
        t2=Thread(target=sleep_task,args=(3,))
        t2.start()
        end_time=time.time()
        print(end_time-srat_time)
    
    # 1.当开启一个程序的时候,会默认启动一个主线程
    # 2.如何在主线等到其他线程执行完以后才继续执行
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    2.1.2 join()方法

    等待指定线程完成后,再接着进行主线程

    import time
    from threading import Thread
    
    
    def sleep_task(sleep_time):
        print("sleep {} seconds start!".format(sleep_time))
        time.sleep(sleep_time)
        print("sleep {} seconds end!".format(sleep_time))
    
    
    if __name__=="__main__":
        srat_time=time.time()
        t1=Thread(target=sleep_task,args=(2,))
        t1.start()
    
        t2=Thread(target=sleep_task,args=(3,))
        t2.start()
    
        t1.join()
        t2.join()
        end_time=time.time()
        print(end_time-srat_time)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    2.1.3 setDaemon(True)守护线程

    在主线程执行完后子线程不管执行完没有都跟着主线程退出

    import time
    from threading import Thread
    
    
    def sleep_task(sleep_time):
        print("sleep {} seconds start!".format(sleep_time))
        time.sleep(sleep_time)
        print("sleep {} seconds end!".format(sleep_time))
    
    
    if __name__=="__main__":
        srat_time=time.time()
    
        t1=Thread(target=sleep_task,args=(2,))
        t1.setDaemon(True) //将t1设为守护线程,要在线程启动之前设置
        t1.start()
    
        t2=Thread(target=sleep_task,args=(3,))
        t2.setDaemon(True)
        t2.start()
    
        end_time=time.time()
        print(end_time-srat_time)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    2.2 继承Thread类

    import time
    from threading import Thread
    
    
    def sleep_task(sleep_time):
        print("sleep {} seconds start!".format(sleep_time))
        time.sleep(sleep_time)
        print("sleep {} seconds end!".format(sleep_time))
    
    class SleepThread(Thread)://SleepThread继承Thread
        def __init__(self, sleep_time):
            super().__init__()
            self.sleep_time=sleep_time
    
        def run(self):
            print("sleep {} seconds start!".format(self.sleep_time))
            time.sleep(self.sleep_time)
            print("sleep {} seconds end!".format(self.sleep_time))
    
    if __name__=="__main__":
        t1=SleepThread(2)
        t2=SleepThread(3)
        t1.start()
        t2.start()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3. GIL

    在这里插入图片描述
    在这里插入图片描述

    4. 线程同步

    from threading import Lock, Thread
    
    total=0
    total_lock=Lock()
    
    def add():
        total_lock.acquire()
        global total
        for i in range(100000):
            total+=1
        total_lock.release()
    
    def desc():
        total_lock.acquire()
        global total
        for i in range(100000):
            total -= 1
        total_lock.release()
    
    
    if __name__=="__main__":
        add=Thread(target=add)
        desc=Thread(target=desc)
        add.start()
        desc.start()
        add.join()
        desc.join()
        print(total)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    先运行完add方法,再运行desc方法。

    5. 关于线程为什么需要Lock

    就比如a,b两个人在微信上取同一张卡的钱,操作如下:
    ①获取余款—>②取款—>③余款减去取款再存入数据库
    因为时间切片不断切换,所以a刚获取余款,就切换到b获取余款,那么两个人获得的余款是一样的(假设为100),然后a取款90,这时又切换到b取款90,然后再各自存款更新。那么余款10,但是a,b合起来取走了180。
    正常过程应该是a取完款就立马更新余款,然后b再获取正确的余款再取款。所以需要Lock,保证一个一个操作,避免乱套。

    from threading import Lock, Thread
    
    total=0
    total_lock=Lock()
    
    def add():
        total_lock.acquire()
        global total
        for i in range(100000):
            total+=1
        total_lock.release()
    
    def desc():
        total_lock.acquire()
        global total
        for i in range(100000):
            total -= 1
        total_lock.release()
    
    
    if __name__=="__main__":
        add=Thread(target=add)
        desc=Thread(target=desc)
        add.start()
        desc.start()
        add.join()
        desc.join()
        print(total)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

  • 相关阅读:
    前端练习小项目 —— 养一只电子蜘蛛
    iOS16更新后打不开微信 解决办法来了
    【面试题】说说你对 async和await 理解
    DOS攻击-ftp_fuzz.py
    C++设计模式-装饰器(Decorator)
    Java关键字this详解
    医药资讯网都有哪些?最值得推荐的有哪些?
    MES系统会采集哪些数据?数据采集方式有哪些?
    CF120F Spiders
    一张图把DCDC电源拓扑“融会贯通”
  • 原文地址:https://blog.csdn.net/heipao17/article/details/125799596