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('主线程退出')

在这里插入图片描述

情况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()))

在这里插入图片描述

情况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()))    

情况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('主线程退出')

在这里插入图片描述

情况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()))

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值