• python 多线程编程(线程同步和守护线程)


    setDaemon(True)为守护主线程,默认为False,随着主线程的终止而终止,不管当前主线程下有多少子线程没有执行完毕,都会终止。
    join()为守护子线程 ,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止。
    参考链接:守护线程和线程同步
    参考链接:线程锁
    下面探究加线程同步和守护线程的情况:

    1. 情况:各个子线程阻塞,确保线程同步,主线程等子线程运行完毕才执行
    2. 情况:各个子线程不阻塞,子线程并行,主线程等子线程运行完毕才执行
    3. 情况:各个子线程不阻塞,不确保线程同步,子线程并行,主线程不等子线程结束,子线程还在执行
    4. 情况:主线程执行完了,子线程不管有没有执行完,都要结束。

    情况1:各个子线程阻塞,确保线程同步,主线程等子线程运行完毕才执行

    # coding:utf-8
    import time
    import random
    import threading
    lists = ['python', 'django', 'tornado','flask', 'bs5', 'requests', 'uvloop']
    new_lists = []
    def work():
        t1= time.time()
        if len(lists) == 0:
            return
        data = random.choice(lists)
        lists.remove(data)
        new_data = '%s_new' % data
        new_lists.append(new_data)
        time.sleep(1)
        t2= time.time()
        print("线程名称{},时间{}".format(t.name, t2-t1))
    
    if __name__ == '__main__':
        # 主线程
        start = time.time()
        t_list = []
        for i in range(len(lists)):
            t = threading.Thread(target=work)
            t_list.append(t)
        t1 = time.time()
        for t in t_list:
            t.start()
            # 等待上一个子线程运行结束后再进行下一个线程,所有子线程结束才执行主线程
            t.join()
            print("当前启动线程名称{},数量{},是否存活{}".format(t.name, threading.active_count(), t.is_alive()))
        t2 = time.time()
        print("主线程分配线程的时间{}".format(t2-t1))
        print('old list:', lists)
        print('new list:', new_lists)
        print('time is %s' % (time.time() - start))
        print('主线程退出')
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    情况2:子线程并行,主线程等子线程运行完毕才执行

        for i in range(len(lists)):
            t = threading.Thread(target=work)
            # 子线程之间并行
            t.start()
            t_list.append(t)
        t1 = time.time()
        for t in t_list:
            # 确保所有子线程运行完,主线程才退出
            t.join()
            print("当前启动线程名称{},数量{},是否存活{}".format(t.name, threading.active_count(), t.is_alive()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    情况3:子线程并行,主线程不等子线程结束,子线程还在执行

    若去掉t.join(),各个线程一起运行,主线程也不等待,结果如下:

        for i in range(len(lists)):
            t = threading.Thread(target=work)
            # 子线程之间并行
            t.start()
            t_list.append(t)
            print("当前启动线程名称{},数量{},是否存活{}".format(t.name, threading.active_count(), t.is_alive()))    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    情况3

    创建的线程是与需要的参数相关,想当于创建了7个线程,去同时执行,且在没有加锁的状态下,但这种方式,处理线程并发数与参数有关,且并发量过高。
    下面使用线程池,使得线程数量与参数无关,此线程池默认子线程守护:子线程运行完在执行主线程

    if __name__ == '__main__':
        # 主线程
        start = time.time()
        # 创建 ThreadPoolExecutor 此线程池默认子线程守护:子线程运行完在执行主线程
        with ThreadPoolExecutor(2) as executor: 
            # 提交任务
            future_list = [executor.submit(work) for i in range(len(lists))]
        for future in as_completed(future_list):
            result = future.result() # 获取任务结果
            print("%s get result : %s" % (threading.current_thread().name, result))
        print('old list:', lists)
        print('new list:', new_lists)
        print('time is %s' % (time.time() - start))
        print('主线程退出')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    情况4:主线程执行完了,子线程不管有没有执行完,都要结束。

        for i in range(len(lists)):
            t = threading.Thread(target=work)
            # # 启动前,先设置守护线程
            t.setDaemon(True)  
            t.start()
            t_list.append(t)
            print("当前启动线程名称{},数量{},是否存活{}".format(t.name, threading.active_count(), t.is_alive()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

  • 相关阅读:
    网络术语介绍 服务器、中间件、数据库、代码、静态资源 客户端,服务器,IP地址,域名,DNS,ISP,TCP/IP,HTTP
    linux 数据恢复
    渗透工具---BurpSuite 插件开发之HelloWorld
    【机器学习】07. 决策树模型DecisionTreeClassifier(代码注释,思路推导)
    5年自动化测试,终于进字节跳动了,年薪30w其实也并非触不可及
    摩尔定律的概念
    网络入侵检测 Network Intrusion Detection System (NIDS)
    一看就会的Chromedriver(谷歌浏览器驱动)安装教程
    Redis实战案例及问题分析之单机优惠券秒杀
    正则表达式
  • 原文地址:https://blog.csdn.net/weixin_43585712/article/details/127866292