>>>>场景:多线程多表入库优化--每个线程对应一张表
import time
import queue
import random
from threading import Thread
'''任务场景
多线程多表入库:
原来的入库队列只有一个主队列,队列里的数据,多为连续同属于属于一个表的数据,
在执行多线程时,由于多个线程都执行同属于一个表的数据,且第一个获取改表的线程会进行锁表,其他线程只能等待
实际效果与单线程相比,效果提升并不明显
举个有味道的例子,你就懂了
---------------------------------------*------------------
厕所有4个坑位,每个坑位只允许一个部门的人上厕所,有一群人排队上厕所,他们都是一个部门的,因为喜欢结伴一起去,
厕所每次进四个人,然而,四个人都是同一个部门的,按规定,只能使用指定的一个坑位,结果就是四个人用一个坑位,等待前一个人用完才能用
效率低下,其他三个坑位没有用,浪费资源
----------------------------------------------------------
优化:
将一个主队列分为多个线程子队列
每个线程子队列处理特定的一个表,这样避免上面出现的锁表等待问题
当线程子队列完成其任务,再次从主队列获取一个表的子队列进行入库
举个有味道的例子,你就懂了
---------------------------------------*------------------
厕所有4个坑位,每个坑位只允许一个部门的人上厕所,有一群人排队上厕所,他们都是一个部门的,因为喜欢结伴一起去,
按部门分为四个队伍,每次厕所进4个人,每个队伍出来一个人,这样就效率提高了,没有浪费坑位
----------------------------------------------------------
'''
class Mysql(Thread):
'模拟数据入库'
def __init__(self,task_queue):
super().__init__()
self.task_queue=task_queue
def run(self):
while not self.task_queue.empty():
self.task_queue.get()
a = random.randint(1, 3)
time.sleep(a)
print('----已处理一个数据------')
class auxiliary_function(object):
'辅助对象'
def __init__(self):
pass
def create_queue(self):
'模拟主队列数据'
for i in range(7):
for j in range(5):
main_que.put(('table'+str(i),j))
def names_var(self):
'生成动态变量'
for i in range(Mysql_thd):
names['queue_' + str(i)] = queue.Queue()
register_dict.update({'queue_' + str(i):-1})
def main_split_queue(self):
'主队列数据分配到子队列'
while not main_que.empty():
table,df=main_que.get()
tmp_queue=False
for key,value in register_dict.items():
if value==-1:
tmp_queue=names.get(key)
register_dict.update({key:table})
tmp_queue.put((table,df))
break
elif value==table:
tmp_queue=names.get(key)
tmp_queue.put((table, df))
break
else:
pass
if not tmp_queue:
main_que.put((table,df))
break
def count_size(self):
'统计每个子队列的含有的数据量'
for key,value in register_dict.items():
tmp_queue=names.get(key)
print(key,tmp_queue.qsize())
def thd_to_mysql(self):
'初始化多线程入库'
for que_id,table_name in register_dict.items():
tmp_queue = names.get(que_id)
sa=Mysql(task_queue=tmp_queue)
sa.start()
thd_dict.update({que_id:sa})
def check_thd_alive(self):
'检测线程是否存活-触发二次分配'
spilt_sign=False
for que_id,thd_id in thd_dict.items():
if not thd_id.is_alive():
register_dict.update({que_id:-1})
spilt_sign=True
if spilt_sign:
self.main_split_queue()
def data_to_sql(self):
'持续多线程入库'
for que_id,table_name in register_dict.items():
tmp_queue = names.get(que_id)
thd_id=thd_dict.get(que_id)
if not thd_id.is_alive():
sa=Mysql(task_queue=tmp_queue)
sa.start()
thd_dict.update({que_id:sa})
def while_mysql(self):
'循环入库-直至入库完成'
self.thd_to_mysql()
while not main_que.empty():
self.check_thd_alive()
self.data_to_sql()
def run(self):
'运行主函数'
self.names_var()
self.create_queue()
self.main_split_queue()
self.while_mysql()
if __name__ == '__main__':
main_que=queue.Queue()
names = locals()
register_dict = {}
Mysql_thd=5
thd_dict={}
example=auxiliary_function()
example.run()