1、什么是线程?
线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。
线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行
2、线程模块详细使用:
a、使用threading模块 from threading import Thread
b、Thread里面的参数使用:
target:指定任务函数
name:设置函数名字
daemon:设置守护线程
kwargs:给任务函数传参数
3、线程对象的方法:
t1=Thread(target=fun1,name=‘yb’,daemon=True,args=(‘张三’,)) #创建一个线程对象
#启动线程执行
t1.start()
#让主线程等待t1执行完
t1.join()
4、多线程之间如何切换:
a、执行时间达到指定的值0.005
b、执行线程遇到IO(input,output)操作
网络io, 文件io,等待(time.sleep)
5、多个线程操作同一个全局资源,会导致数据丢失:
解决方案:
a、加锁 全局数据修改的那行代码使用锁锁起来
Lock:线程锁
acquire()锁定: release()释放锁:
b、使用队列(或者是数据库)存储数据
from queue import Queue
创建队列 q=Queue(3)
写入队列
q.put(‘111’)
获取队列
q.get()
6、比多线程更简单的线程池:
from concurrent.futures.thread import ThreadPoolExecutor
#创建线程池对象,max_workers代表最大可用线程数为5
with ThreadPoolExecutor(max_workers=5) as tp:
for i in range(5):
tp.submit(work) 创建5个线程并执行,work为方法名
7、线程可以用来做什么,实战:
处理很多数据的情况下,执行比较慢,可使用多线程 比如:
a、通过调10万次接口创建10万条数据
b、获取10万条数据对这些数据进行校验(数据迁移)
像之前销量对比的脚本跑500条数据处理花费了70s+:
代码改造后使用多线程只花了4s
c、对一些自动化框架的2次开发,用例执行器使用,像unittest里面执行test下面的所有用例会用到
from scrips.handle_mysql import HandleMysql
import time
from threading import Thread,Lock
from concurrent.futures.thread import ThreadPoolExecutor
from queue import Queue
# def duibixiaoliang():
# do_mysql_kp = HandleMysql()
# sql = 'select * from kaipao.item_sku order by id desc limit 0,500'
# mysql_data = do_mysql_kp.run(sql)
#
#
# for i in mysql_data:
# sellcnt=i.get('sellcnt')
# id=i.get('id')
# print(f"item_sk表商品id为{id}的销量数据为:{sellcnt}")
#
# sql_item = f'select * from item.item_sku WHERE id={id}'
# mysql_data_item = do_mysql_kp.run(sql_item)
# item_sellcnt=mysql_data_item[0]['sell_count']
# print(f"item表商品id为{id}的销量数据为:{item_sellcnt}")
# if sellcnt==item_sellcnt:
# print(f"商品ID为{id}的数据对比正常")
# else:
# print(f"商品ID为{id}的数据对比异常")
# a = time.time()
#
# duibixiaoliang()
#
# b=time.time()
# print(b-a)
a=Queue()
b=Queue()
c=Queue()
def sc():
do_mysql_kp = HandleMysql()
sql = 'select * from kaipao.item_sku order by id desc limit 0,500'
mysql_data = do_mysql_kp.run(sql)
for i in mysql_data:
sellcnt = i.get('sellcnt')
id = i.get('id')
sql_item = f'select * from item.item_sku WHERE id={id}'
a.put(sql_item)
b.put(sellcnt)
c.put(id)
print("生成数据完成")
def duibixiaoliang():
while True:
try:
item=a.get(timeout=1)
sellcnt=b.get(timeout=1)
id=c.get(timeout=1)
do_mysql_kp = HandleMysql()
mysql_data_item = do_mysql_kp.run(item)
print(mysql_data_item)
item_sellcnt=mysql_data_item[0]['sell_count']
print(f"item表商品id为{id}的销量数据为:{item_sellcnt}")
if sellcnt==item_sellcnt:
print(f"商品ID为{id}的数据对比正常")
else:
print(f"商品ID为{id}的数据对比异常")
except:
return
else:
print(item,sellcnt,id)
a.task_done()
b.task_done()
c.task_done()
str = time.time()
with ThreadPoolExecutor(max_workers=100) as tp:
tp.submit(sc)
for i in range(50):
tp.submit(duibixiaoliang)
end=time.time()
print(end-str)
# t1=Thread(target=sc)
# t1.start()
# for i in range(3):
# Thread(target=duibixiaoliang).start()
# t1.join()
# a.join()