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

Python 守护进程 守护线程 python中守护线程_Python 守护进程 守护线程

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

Python 守护进程 守护线程 python中守护线程_子线程_02

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

Python 守护进程 守护线程 python中守护线程_开发语言_03

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

Python 守护进程 守护线程 python中守护线程_Python 守护进程 守护线程_04

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

Python 守护进程 守护线程 python中守护线程_Python 守护进程 守护线程_05