• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Python多线程编程之threading模块详解

    一、介绍

    线程是什么?线程有啥用?线程和进程的区别是什么?

    线程是操作系统能够进行运算调度的最小单位。被包含在进程中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

    二、Python如何创建线程

    2.1 方法一:

    创建Thread对象

    步骤:

    1.目标函数

    2.实例化Thread对象

    3.调用start()方法


    import threading
    
    
    # 目标函数1
    def fun1(num):
        for i in range(num):
            print('线程1: 第%d次循环:' % i)
    
    
    # 目标函数2
    def fun2(lst):
        for ele in lst:
            print('线程2: lst列表中元素 %d' % ele)
    
    
    def main():
        num = 10
        # 实例化Thread对象
        # target参数一定为一个函数,且不带括号
        # args参数为元组类型,参数为一个时一定要加逗号
        t1 = threading.Thread(target=fun1, args=(num,))
        t2 = threading.Thread(target=fun2, args=([1, 2, 3, 4, 5],))
    
        # 调用start方法
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
    

    2.2 方法二:

    创建子类继承threading.Thread类

    import threading
    import os
    
    
    class Person(threading.Thread):
        def run(self):
            self.sing(5)
            self.cook()
    
        @staticmethod
        def sing(num):
            for i in range(num):
                print('线程[%d]: The person sing %d song.' % (os.getpid(), i))
    
        @staticmethod
        def cook():
            print('线程[%d]:The person has cooked breakfast.' % os.getpid())
    
    
    def main():
        p1 = Person()
        p1.start()
    
        p2 = Person()
        p2.start()
    
    
    if __name__ == '__main__':
        main()
    

    三、线程的用法

    3.1 确定当前的线程

    import threading
    import time
    import logging
    
    
    def fun1():
        print(threading.current_thread().getName(), 'starting')
        time.sleep(0.2)
        print(threading.current_thread().getName(), 'exiting')
    
    
    def fun2():
        # print(threading.current_thread().getName(), 'starting')
        # time.sleep(0.3)
        # print(threading.current_thread().getName(), 'exiting')
        logging.debug('starting')
        time.sleep(0.3)
        logging.debug('exiting')
    
    
    logging.basicConfig(
        level=logging.DEBUG,
        format='[%(levelname)s] (%(threadName)-10s) %(message)s'
    )
    
    
    def main():
        t1 = threading.Thread(name='线程1', target=fun1)
        t2 = threading.Thread(name='线程2', target=fun2)
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
    

    3.2 守护线程

    区别

    守护线程如何搞

    import threading
    import time
    import logging
    
    
    def daemon():
        logging.debug('starting')
        # 添加延时,此时主线程已经退出,exiting不会打印
        time.sleep(0.2)
        logging.debug('exiting')
    
    
    def non_daemon():
        logging.debug('starting')
        logging.debug('exiting')
    
    
    logging.basicConfig(
        level=logging.DEBUG,
        format='[%(levelname)s] (%(threadName)-10s) %(message)s'
    )
    
    
    def main():
        # t1 = threading.Thread(name='线程1', target=daemon)
        # t1.setDaemon(True)
        t1 = threading.Thread(name='线程1', target=daemon, daemon=True)
        t2 = threading.Thread(name='线程2', target=non_daemon)
        t1.start()
        t2.start()
    
        # 等待守护线程完成工作需要调用join()方法,默认情况join会无限阻塞,可以传入浮点值,表示超时时间
        t1.join(0.2)
        t2.join(0.1)
    
    
    if __name__ == '__main__':
        main()
    
    

    3.3 控制资源访问

    目的:

    Python线程中资源共享,如果不对资源加上互斥锁,有可能导致数据不准确。

    import threading
    import time
    
    
    g_num = 0
    
    
    def fun1(num):
        global g_num
        for i in range(num):
            g_num += 1
        print('线程1 g_num = %d' % g_num)
    
    
    def fun2(num):
        global g_num
        for i in range(num):
            g_num += 1
        print('线程2 g_num = %d' % g_num)
    
    
    def main():
        t1 = threading.Thread(target=fun1, args=(1000000,))
        t2 = threading.Thread(target=fun1, args=(1000000,))
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
        time.sleep(1)
        print('主线程 g_num = %d' % g_num)
    
    

    互斥锁

    import threading
    import time
    
    
    g_num = 0
    L = threading.Lock()
    
    
    def fun1(num):
        global g_num
        L.acquire()
        for i in range(num):
            g_num += 1
        L.release()
        print('线程1 g_num = %d' % g_num)
    
    
    def fun2(num):
        global g_num
        L.acquire()
        for i in range(num):
            g_num += 1
        L.release()
        print('线程2 g_num = %d' % g_num)
    
    
    def main():
        t1 = threading.Thread(target=fun1, args=(1000000,))
        t2 = threading.Thread(target=fun1, args=(1000000,))
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
        time.sleep(1)
        print('主线程 g_num = %d' % g_num)
    

    互斥锁引发的另一个问题:死锁

    死锁产生的原理:

    import threading
    import time
    
    
    g_num = 0
    L1 = threading.Lock()
    L2 = threading.Lock()
    
    
    def fun1():
        L1.acquire(timeout=5)
        time.sleep(1)
        L2.acquire()
        print('产生死锁,并不会打印信息')
        L2.release()
        L1.release()
    
    
    def fun2():
        L2.acquire(timeout=5)
        time.sleep(1)
        L1.acquire()
        print('产生死锁,并不会打印信息')
        L1.release()
        L2.release()
    
    
    def main():
        t1 = threading.Thread(target=fun1)
        t2 = threading.Thread(target=fun2)
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
        time.sleep(1)
        print('主线程 g_num = %d' % g_num)
    
    

    如何避免产生死锁:

    锁超时操作

    import threading
    import time
    
    
    g_num = 0
    L1 = threading.Lock()
    L2 = threading.Lock()
    
    
    def fun1():
        L1.acquire()
        time.sleep(1)
        L2.acquire(timeout=5)
        print('超时异常打印信息1')
        L2.release()
        L1.release()
    
    
    def fun2():
        L2.acquire()
        time.sleep(1)
        L1.acquire(timeout=5)
        print('超时异常打印信息2')
        L1.release()
        L2.release()
    
    
    def main():
        t1 = threading.Thread(target=fun1)
        t2 = threading.Thread(target=fun2)
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
        time.sleep(1)
        print('主线程 g_num = %d' % g_num)
    

    到此这篇关于Python多线程编程之threading模块详解的文章就介绍到这了,更多相关python threading模块内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • 分析Python感知线程状态的解决方案之Event与信号量
    • 像线程一样管理进程的Python multiprocessing库
    • Python爬虫之线程池的使用
    • 深入理解python多线程编程
    • Python一些线程的玩法总结
    上一篇:python类的继承链实例分析
    下一篇:Python OpenCV实现基本图形绘制
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Python多线程编程之threading模块详解 Python,多,线程,编程,之,threading,