一.背景:
当数据量过大时,一个程序的执行时间就会主要花费在等待单次查询返回结果,在这个过程中cpu无疑是处于等待io的空闲状态的,这样既浪费了cpu资源,又花费了大量时间(当然这里主要说多线程,批量查询不在考虑范围,总会存在不能批量查询的情况),在这种非密集型运算(及大量占用cpu资源)的情况下在python中无疑运用多线程是一个非常棒的选择。
二.知识点:
数据库连接池的运用及优势,python中多线程的运用,队列的运用
数据库连接池:限制了数据库的连接最大个数,每次连接都是可以重复使用的,当然也可以限制每个连接的重复使用次数(这个在这里是没必要的),需要注意的是设置的数据库的最大连接个数最好要大于我们自己开的最大线程个数,一般逻辑是每个线程占用一个数据库连接可以使程序达到最大速度,如果小于则可能存在同时连接个数大于数据库允许的最大连接个数的风险。使用数据库连接池的优势在于,python多线程并发操作数据库,会存在链接数据库超时、数据库连接丢失、数据库操作超时等问题,而数据库连接池提供线程间可共享的数据库连接,并自动管理连接。
python多线程:在程序等待io的时间里调用多线程去数据库执行查询操作。
队列:这个就是数据结构里面的知识了,一般队列的常用模式先进先出队列。(这里主要用的是队列取一个数就少一个数的原理,其实用列表也可以实现,他的先进先出主要强调的是一个顺序关系,这一点到没用上,就当是练练手了)
三.两段代码作比较:
数据库的截图:
第一段代码:正常循环查询并打印出执行时间
#!/usr/bin/python # -*- coding=utf-8 -*- import time import threading import MySQLdb import Queue from MySQLdb.cursors import DictCursor from DBUtils.PooledDB import PooledDB def mysql_connection(): host = 'localhost' user = 'root' port = 3306 password = '123456' db = 'test' charset = 'utf8' limit_count = 3 # 最低预启动数据库连接数量 pool = PooledDB(MySQLdb, limit_count, maxconnections=15, host=host, user=user, port=port, passwd=password, db=db, charset=charset, use_unicode=True, cursorclass=DictCursor) return pool start = time.time() pool = mysql_connection() for id in range(50): con = pool.connection() cur = con.cursor() sql = '''select id,name,age,weight from test where id = %s '''%id cur.execute(sql) time.sleep(0.5) result = cur.fetchall() if result: print('this is tread %s (%s,%s,%s,%s)'%(id,result[0]['id'],result[0]['name'],result[0]['age'],result[0]['weight'])) else: print('this tread %s result is none'%id) end = time.time() - start print(end)
执行结果:
第二段代码:限制数据库连接池最大15个连接,用队列限制最大线程个数为10个
#!/usr/bin/python # -*- coding=utf-8 -*- import time import threading import MySQLdb import Queue from MySQLdb.cursors import DictCursor from DBUtils.PooledDB import PooledDB def mysql_connection(): host = 'localhost' user = 'root' port = 3306 password = '123456' db = 'test' charset = 'utf8' limit_count = 3 # 最低预启动数据库连接数量 pool = PooledDB(MySQLdb, limit_count, maxconnections=15, host=host, user=user, port=port, passwd=password, db=db, charset=charset, use_unicode=True, cursorclass=DictCursor) return pool def tread_connection_db(id): con = pool.connection() cur = con.cursor() sql = '''select id,name,age,weight from test where id = %s '''%id cur.execute(sql) time.sleep(0.5) result = cur.fetchall() if result: print('this is tread %s (%s,%s,%s,%s)'%(id,result[0]['id'],result[0]['name'],result[0]['age'],result[0]['weight'])) else: print('this tread %s result is none'%id) con.close() if __name__=='__main__': start = time.time() #创建线程连接池,最大限制15个连接 pool = mysql_connection() #创建队列,队列的最大个数及限制线程个数 q=Queue.Queue(maxsize=10) #测试数据,多线程查询数据库 for id in range(50): #创建线程并放入队列中 t = threading.Thread(target=tread_connection_db, args=(id,)) q.put(t) #队列队满 if q.qsize()==10: #用于记录线程,便于终止线程 join_thread = [] #从对列取出线程并开始线程,直到队列为空 while q.empty()!=True: t = q.get() join_thread.append(t) t.start() #终止上一次队满时里面的所有线程 for t in join_thread: t.join() end = time.time() - start print(end)
程序备注应该还算比较清晰的哈,程序执行结果:
四.结论:
看结果说话
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】