• Python21天学习挑战赛Day(8)·多线程(threading模块)(应用)



    活动地址:CSDN21天学习挑战赛

    学习日志4——

            1.多任务

    操作系统轮流让各个任务交替执行,表面看为交替执行,但由于CPU执行速度极快,呈现出来的效果和同步执行一样。

            注意:

    ·并发:任务数多于CPU核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不再执行,因为切换任务速度相当快,看上去一起执行而已)。

    ·并行:任务数小于等于CPU核数,即任务真的是一起执行的。

            2.threading模块

    2.1常用方法——

     2.2Thread类使用说明——

     使用Thread 创建线程方法:

            1.为构造函数传递一个可调用对象

            2.继承Thread类并在子类中重写   _init_()和 run()方法

    2.3线程对象 threading.Thread 的方法和属性 ——

    2.4实例化 threading.Thread()  ——

            2.4.1 单线程执行

    1. #coding=utf-8
    2. import threading
    3. import time
    4. def hearing():
    5. print("干啥啥不行,躺平第一名")
    6. time.sleep(1)
    7. if __name__ == "__main__":
    8. for i in range(5):
    9. hearing()

            2.4.2 使用threading模块

    1. #coding=utf-8
    2. import threading
    3. import time
    4. def hearing():
    5. print("干啥啥不行,躺平第一名")
    6. time.sleep(1)
    7. if __name__ == "__main__":
    8. for i in range(5):
    9. t=threading.Thread(target=hearing)
    10. t.start()#启动线程

            多线程耗时更短,调用start()时,才会真正创建线程,并执行。

            2.4.3 主线程会等待所有子线程结束后结束

    1. #coding=utf-8
    2. import threading
    3. import time
    4. from time import sleep,ctime
    5. def hearing():
    6. print("干啥啥不行,躺平第一名")
    7. time.sleep(1)
    8. def watching():
    9. print("吃啥啥不剩,能吃是福")
    10. time.sleep(1)
    11. def saying():
    12. print("我乐意")
    13. time.sleep(1)
    14. if __name__ == "__main__":
    15. for i in range(5):
    16. print("---开始---:%s"%ctime())
    17. t1=threading.Thread(target=hearing)
    18. t2=threading.Thread(target=watching())
    19. t3=threading.Thread(target=saying())
    20. t1.start()#启动线程
    21. t2.start()
    22. t3.start()
    23. sleep(2)
    24. print("---结束---:%s"%ctime())

    输出——

            2.4.4 查看线程数量

            

    1. #coding=utf-8
    2. import threading
    3. import time
    4. from time import sleep,ctime
    5. def hearing():
    6. print("干啥啥不行,躺平第一名")
    7. #time.sleep(1)
    8. def watching():
    9. print("吃啥啥不剩,能吃是福")
    10. #time.sleep(1)
    11. def saying():
    12. print("我乐意")
    13. #time.sleep(1)
    14. if __name__ == "__main__":
    15. for i in range(2):
    16. print("---开始---:%s"%ctime())
    17. t1=threading.Thread(target=hearing)
    18. t2=threading.Thread(target=watching())
    19. t3=threading.Thread(target=saying())
    20. t1.start()#启动线程
    21. t2.start()
    22. t3.start()
    23. while True:
    24. length=len(threading.enumerate())
    25. print("当前运行线程数量:%d"%length)
    26. if length<=1:
    27. break
    28. #sleep(1)
    29. print("---结束---:%s"%ctime())

    运行结果——

    2.5 继承 threading.Thread

             2.5.1 线程执行代码的封装

    1. #coding=utf-8
    2. import threading
    3. import time
    4. class MyThread(threading.Thread):
    5. def run(self):
    6. for i in range(3):
    7. time.sleep(1)
    8. msg = "I'm "+self.name+' @ '+str(i) #name属性中保存的是当前线程的名字
    9. print(msg)
    10. if __name__ == '__main__':
    11. t = MyThread()
    12. t.start()

     

             2.5.2 线程执行顺序

    1. #coding=utf-8
    2. import threading
    3. import time
    4. class MyThread(threading.Thread):
    5. def run(self):
    6. for i in range(3):
    7. time.sleep(1)
    8. msg = "I'm "+self.name+' @ '+str(i)
    9. print(msg)
    10. def test():
    11. for i in range(5):
    12. t = MyThread()
    13. t.start()
    14. if __name__ == '__main__':
    15. test()

    运行结果——

     

             2.5.3 多线程-共享全局变量

    1. from threading import Thread
    2. import time
    3. g_num = 100
    4. def work1():
    5. global g_num
    6. for i in range(3):
    7. g_num += 1
    8. print("----in work1, g_num is %d---"%g_num)
    9. def work2():
    10. global g_num
    11. print("----in work2, g_num is %d---"%g_num)
    12. print("---线程创建之前g_num is %d---"%g_num)
    13. t1 = Thread(target=work1)
    14. t1.start()
    15. #延时一会,保证t1线程中的事情做完
    16. time.sleep(1)
    17. t2 = Thread(target=work2)
    18. t2.start()

    运行结果——

             2.5.4列表当作实参传递到线程中

    1. from threading import Thread
    2. import time
    3. def work1(nums):
    4. nums.append(44)
    5. print("----in work1---",nums)
    6. def work2(nums):
    7. #延时一会,保证t1线程中的事情做完
    8. time.sleep(1)
    9. print("----in work2---",nums)
    10. g_nums = [11,22,33]
    11. t1 = Thread(target=work1, args=(g_nums,))
    12. t1.start()
    13. t2 = Thread(target=work2, args=(g_nums,))
    14. t2.start()

     

             2.5.5 多线程-全局变量问题

    test1:

    1. import threading
    2. import time
    3. g_num = 0
    4. def work1(num):
    5. global g_num
    6. for i in range(num):
    7. g_num += 1
    8. print("----in work1, g_num is %d---"%g_num)
    9. def work2(num):
    10. global g_num
    11. for i in range(num):
    12. g_num += 1
    13. print("----in work2, g_num is %d---"%g_num)
    14. print("---线程创建之前g_num is %d---"%g_num)
    15. t1 = threading.Thread(target=work1, args=(100,))
    16. t1.start()
    17. t2 = threading.Thread(target=work2, args=(100,))
    18. t2.start()
    19. while len(threading.enumerate()) != 1:
    20. time.sleep(1)
    21. print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

    结果

    test2:

    1. import threading
    2. import time
    3. g_num = 0
    4. def work1(num):
    5. global g_num
    6. for i in range(num):
    7. g_num += 1
    8. print("----in work1, g_num is %d---"%g_num)
    9. def work2(num):
    10. global g_num
    11. for i in range(num):
    12. g_num += 1
    13. print("----in work2, g_num is %d---"%g_num)
    14. print("---线程创建之前g_num is %d---"%g_num)
    15. t1 = threading.Thread(target=work1, args=(1000000,))
    16. t1.start()
    17. t2 = threading.Thread(target=work2, args=(1000000,))
    18. t2.start()
    19. while len(threading.enumerate()) != 1:
    20. time.sleep(1)
    21. print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

    3.线程同步

     4.互斥锁

     threading模块中定义了Lock类,可以方便的处理锁定

    1. # 创建锁
    2. mutex = threading.Lock()
    3. # 锁定
    4. mutex.acquire()
    5. # 释放
    6. mutex.release()

     

     使用互斥锁完成2个线程对同一个全局变量各加100万次的操作

    1. import threading
    2. import time
    3. g_num = 0
    4. def test1(num):
    5. global g_num
    6. for i in range(num):
    7. mutex.acquire() # 上锁
    8. g_num += 1
    9. mutex.release() # 解锁
    10. print("---test1---g_num=%d"%g_num)
    11. def test2(num):
    12. global g_num
    13. for i in range(num):
    14. mutex.acquire() # 上锁
    15. g_num += 1
    16. mutex.release() # 解锁
    17. print("---test2---g_num=%d"%g_num)
    18. # 创建一个互斥锁
    19. # 默认是未上锁的状态
    20. mutex = threading.Lock()
    21. # 创建2个线程,让他们各自对g_num加1000000次
    22. p1 = threading.Thread(target=test1, args=(1000000,))
    23. p1.start()
    24. p2 = threading.Thread(target=test2, args=(1000000,))
    25. p2.start()
    26. # 等待计算完成
    27. while len(threading.enumerate()) != 1:
    28. time.sleep(1)
    29. print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

     

     

     5.死锁

     

    1. import threading
    2. import time
    3. class MyThread1(threading.Thread):
    4. def run(self):
    5. # 对mutexA上锁
    6. mutexA.acquire()
    7. # mutexA上锁后,延时1秒,等待另外那个线程 把mutexB上锁
    8. print(self.name+'----do1---up----')
    9. time.sleep(1)
    10. # 此时会堵塞,因为这个mutexB已经被另外的线程抢先上锁了
    11. mutexB.acquire()
    12. print(self.name+'----do1---down----')
    13. mutexB.release()
    14. # 对mutexA解锁
    15. mutexA.release()
    16. class MyThread2(threading.Thread):
    17. def run(self):
    18. # 对mutexB上锁
    19. mutexB.acquire()
    20. # mutexB上锁后,延时1秒,等待另外那个线程 把mutexA上锁
    21. print(self.name+'----do2---up----')
    22. time.sleep(1)
    23. # 此时会堵塞,因为这个mutexA已经被另外的线程抢先上锁了
    24. mutexA.acquire()
    25. print(self.name+'----do2---down----')
    26. mutexA.release()
    27. # 对mutexB解锁
    28. mutexB.release()
    29. mutexA = threading.Lock()
    30. mutexB = threading.Lock()
    31. if __name__ == '__main__':
    32. t1 = MyThread1()
    33. t2 = MyThread2()
    34. t1.start()
    35. t2.start()

     

     

  • 相关阅读:
    Visual Studio快捷键记录
    go脚本示例
    java---高斯消元---线性方程组(每日一道算法2022.9.20)
    设计模式之概述篇
    Java 客户端调用 WebService 接口的一种方式
    3D着色器(OpenGL)
    jenkins结合k8s部署动态slave
    Android Manifest 标签解析
    worthington细胞分离技术丨生存能力测量优化方案
    JavaSE——遍历Map集合
  • 原文地址:https://blog.csdn.net/weixin_62599885/article/details/126235214