【小菜虫学习笔记-Python多线程自检测脚本】
前言
由于本人在实际的工作中运行多线程脚本,线程数经常越跑越少,于是通过阅读官方文档想到了这种解决方案。基于threading的一种多线程监控脚本。
一、threading的官方简介
- 在 CPython 中,由于存在 全局解释器锁,同一时刻只有一个线程可以执行 Python 代码(虽然某些性能导向的库可能会去除此限制)。 如果你想让你的应用更好地利用多核心计算机的计算资源,推荐你使用 multiprocessing 或 concurrent.futures.ProcessPoolExecutor。 但是,如果你想要同时运行多个 I/O 密集型任务,则多线程仍然是一个合适的模型。
- 官方文档:threading — 基于线程的并行
二、使用步骤
1.常用方法
代码如下(示例):
import threading
import time
def run(index):
print(f'我是第 {index} 个线程, name: {thread.name}')
time.sleep(index)
for i in range(5):
thread = threading.Thread(target=run, args=(i,), name=f'name_{i}')
thread.start()
2.实际的应用场景需求
- 消费者需要不停的向生产者请求数据
- 采用多线程的方式提高运行效率
- 检测每个线程的运行状态,如果线程结束或者是因异常终止,就拉起终止的线程数,保证始终有指定的线程数在运行
3.方案实现
- 查阅官方文档中的介绍发现 enumerate 方法刚好满足需求
threading.enumerate()
返回当前所有存活的 Thread 对象的列表。 该列表包括守护线程以及 current_thread() 创建的空线程。 它不包括已终结的和尚未开始的线程。 但是,主线程将总是结果的一部分,即使是在已终结的时候。
- 通过一个简单的实例,可以发现 enumerate方法返回的是一个列表,并且包含了线程的名称
- 最终实现
import re
import time
import threading
def run(index):
print(f'我是第 {index} 个线程, name: {thread.name}')
time.sleep(index)
def detection_of_thread():
while True:
thread_list = threading.enumerate()
# 用来存储还在运行的线程的索引
viable_thread_list = []
for _thread in thread_list:
if re.findall(r'name_(\d*)', _thread.getName()):
# 将还在运行的线程的索引加入打列表中
viable_thread_list.append(re.findall(r'name_(\d*)', _thread.getName())[0])
else:
pass
# 通过判断列表中的索引数是否与指定要开始的线程数相等,相等则说明线程都在运行中
if len(viable_thread_list) == thread_num:
pass
else:
for index in range(1, thread_num+1):
# 通过遍历来判断哪个线程已经运行结束, 然后再次启动
if index not in viable_thread_list:
print(f'我是第{index}个线程, 我暴毙了,被抬进了急症室')
death = threading.Thread(target=run, args=(index,), name=f'name_{index}')
death.start()
print(f'我是第{index}个线程, 我又活过来了')
time.sleep(1)
if __name__ == '__main__':
thread_num = 5
for i in range(1, thread_num+1):
thread = threading.Thread(target=run, args=(i,), name=f'name_{i}')
thread.start()
# 启动检测的线程
detection = threading.Thread(target=detection_of_thread, name='detection')
detection.start()
总结
多多阅读官方文档