最近在用django进行开发,后台用到MySQL数据库,由于查询语句的嵌套,实现起来是在太慢,之前师兄跟我提过用多线程进行操作,我也没怎么接触过,于是就搁置一旁了,当时的主要目的是为了赶出几个小东西,就没有太在意速度这个问题,其实当时也在思考过这个可能是“最关键”的问题。
终于项目赶出来了一点小的成果,就遇到速度的问题,就开始多线程之旅,下面是我总结的一些小小的代码经验,仅供大家参考。
第一种解决方案:
import multiprocessing
def multiTask(tasklist,host,port,user,password,database,item_tbname,keyword,search_rule):
for i in range(0,len(tasklist),20): # 每次取20个任务
tasktemp = tasklist[i:i+20]
job=[] # 初始化每次执行的线程
if i <20:
print(getDate()+":"+"Begin_Project:"+str(len(tasklist)))
print(getDate()+":"+"Process:"+str(round((i+10)*100/len(tasklist),0))+"%")
for j in range(0,len(tasktemp)): # 此处创建20个线程
ptask = (host,port,user,password,database,item_tbname,keyword,search_rule,tasktemp[j][0])
# info
p = multiprocessing.Process(target = func,args=(ptask,)) # func是运行的函数名称,args是传入的参数
p.start()
job.append(p)
for p in job:
p.join()</span>
此处注意的是有两个函数值得注意,一个就是start(),另一个就是join(),在这里我就不详细展开说了,相信大家都可以百度谷歌到,我想提醒大家一个的就是对于下面这条语句
p = multiprocessing.Process(target = func,args=(ptask,))
这个函数的func后面不用加括号(),还有如果只有一个蚕食一定记得后面的args中的逗号‘,’不要遗漏,这是为了标注args是一个list。
第二种解决方案:
第一种解决方案基本上可以解决一些基本的多线程问题,后来我想加入list参数,让每个线程执行的结果作为一个dict拼接到一起,可是怎么弄都没有很好的解决这个问题,也是捣鼓半天,后来就想换种解决方案。主要参考网上一位仁兄的代码:Python多线程异步获得多函数调用的返回值 ,稍加修改就行了,下面贴出我修改的代码:
class MyThread(object):
def __init__(self, func_list=None):
self.func_list = func_list
self.threads = []
def set_thread_func_list(self, func_list):
"""
@note: func_list是一个list,每个元素是一个dict,有func和args两个参数
"""
self.func_list = func_list
@staticmethod
def trace_func(func, *args, **kwargs):
"""
@note:替代profile_func,新的跟踪线程返回值的函数,对真正执行的线程函数包一次函数,以获取返回值
"""
func(*args, **kwargs)
def start(self):
"""
@note: 启动多线程执行,并阻塞到结束
"""
self.threads = []
for func_dict in self.func_list:
if func_dict["args"]:
new_arg_list = [func_dict["func"]]
for arg in func_dict["args"]:
new_arg_list.append(arg)
new_arg_tuple = tuple(new_arg_list)
task = threading.Thread(target=self.trace_func, args=new_arg_tuple)
else:
task = threading.Thread(target=self.trace_func, args=(func_dict["func"],))
self.threads.append(task)
for thread_obj in self.threads:
thread_obj.start()
for thread_obj in self.threads:
thread_obj.join()</span>
for i in range(0, len(Result_itemnum), 5):
tasktemp_itemnum = Result_itemnum[i:i + 5]
mt = MyThread()
g_func_list = []
for j in range(0, len(tasktemp_itemnum)):
g_func_list.append(
{"func": self.run_itemnum,
"args": (selectdb, ordertable, itemtable, category, day, sellernick, tasktemp_itemnum[j][0], List_te)})
mt.set_thread_func_list(g_func_list)
mt.start()
其中下面一部分是我自己实现的一些代码,其中参数部分的List_te是我传进去的参数。基本上能实现一些参数的修改,Python中没有C语言中所谓的传值与传引用的差别,Python把所有到当作对象来处理,传的参数可以叫做对象对象引用。