#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import queue
import time
"""
对照着武老师的课程自己跟着做了一个线程池,主要的思路就是把要执行的任务放进队列中
然后创建若干个线程不断地从队列中获取任务并执行
相对比low B 版的线程池有很大改进,姑且叫low A版吧。。。
"""
Stop_Flag = object()
class ThreadPool(object):
def __init__(self,max_num):
self.max_num = max_num
#创建一个队列用于保存任务
self.queue = queue.Queue()
#创建一个列表保存已经创建的线程
self.generate_list = []
#创建一个列表保存当前空闲的线程
self.free_list = []
#是否结束任务的标志
self.terminate_flag = False
def run(self, func, args, callback=None):
w = (func, args, callback,)
self.queue.put(w) #把相关的参数放入队列当中
if len(self.generate_list)< self.max_num and len(self.free_list) == 0:
self.generate()
def generate(self):
t = threading.Thread(target=self.call)
t.start()
def call(self):
####获取当前的线程对象,并添加到已创建线程的列表当中
current_thread = threading.current_thread()
self.generate_list.append(current_thread)
work = self.queue.get()
#从队列中获取相关的任务信息
while work != Stop_Flag:
func, args, callback = work
try:
ret = func(*args)
except Exception as e:
print(e)
if callback:
try:
callback(ret)
except Exception as ex:
print(ex)
###上面为一个线程执行一次任务的完整流程,一旦线程创建之后,则不断地从队列中获取任务
######在执行完一次任务和获取下一次任务的空当内,线程处于空闲状态
if self.terminate_flag:
break
else:
self.free_list.append(current_thread)
work = self.queue.get()
self.free_list.append(current_thread)
##在开始时或者在循环过程中接收到Stop_Flag时,都会执行下面的语句
self.generate_list.remove(current_thread)
def close(self):
#当只是完成上面的代码的情况下,主进程不会立即结束, ^ ^ 因为这个时候并没有把Stop_Flag传入队列
for i in range(len(self.generate_list)):
self.queue.put(Stop_Flag)
def terminate(self):
self.terminate_flag = True
def do(i):
# time.sleep(0.5)
print(i)
def c():
pass
pool = ThreadPool(10)
for i in range(50):
pool.run(func=do, args=(i,))
pool.terminate()
# pool.close()