setDaemon(True)为守护主线程,默认为False,随着主线程的终止而终止,不管当前主线程下有多少子线程没有执行完毕,都会终止。
join()为守护子线程 ,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止。
参考链接:守护线程和线程同步
参考链接:线程锁
下面探究加线程同步和守护线程的情况:
# 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('主线程退出')
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()))
若去掉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()))
创建的线程是与需要的参数相关,想当于创建了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('主线程退出')
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()))