守护线程: 随着主线程的终止而终止,不管当前主线程下有多少子线程没有执行完毕,都会终止。
线程同步: 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:returndata = random.choice(lists)lists.remove(data)new_data = '%s_new' % datanew_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('new_list len', len(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()))