1、多线程、多进程
a、基础定义
进程:
一个程序,是一组资源的集合。
一个进程里边有一个默认线程,即主线程。
多进程可以利用多核CPU。
线程:
线程是最小的执行单位。
线程和线程之间是相互独立,但可以共享数据。
主线程会等待子线程执行结束。
※Python的多线程为伪多线程,无法有限利用多核CPU。实际上只能利用单核。
原因为全局解释器锁:GIL
b、创建线程
创建线程需声明import threading,该模块为Python自带,无需下载。
之后使用threading.Thread(target=XX)来定义子线程,其中XX为方法名。即使用新线程调用执行XX方法。
最后使用.start()方法来调用线程。
importthreadingimporttimedefclean():print('打扫卫生')
time.sleep(2)defxiyifu():print('洗衣服')
time.sleep(3)defcook():print('做饭')
time.sleep(1)
start_time=time.time()
t= threading.Thread(target=clean) #创建子线程
t2 = threading.Thread(target=xiyifu)
t3= threading.Thread(target=cook)
t.start()#运行子线程
t2.start()
t3.start()
c、确认线程执行完毕
i、使用.join()方法来等待进程执行完毕(正常退出或者抛出未处理的异常)。
※多线程时可以将线程append进list中,再for循环调用join方法确认线程执行完毕。
ii、通过判断当前存活的线程数来判断线程是否执行完毕。
※线程执行完毕后会自动释放线程资源,因此当多线程执行完毕后,当前存活线程将只剩下一个主线程。
※即可以使用threading.active_count()方法来取得当前存活线程数,当该数字为1时,即线程执行完毕。
#1、等待多个子线程执行结束,把启动的子线程放到list中,在循环调用t.join
thread_list =[]for i in range(10):
t= threading.Thread(target=export_data)
thread_list.append(t)
t.start()for t inthread_list:
t.join()print('数据都导完了')#2、等待多个子线程执行结束,通过判断当前线程数
for i in range(10):
t= threading.Thread(target=export_data,args=['db1','a.xls'])
t.start()while threading.active_count() != 1:pass
print(result_list)print('数据都导完了')
d、守护线程
守护线程依赖于主线程,当主线程执行完毕后,无论子线程是否执行完成,都将自动结束线程。
在创建线程时使用.setDaemon(True)方法来设置守护线程,当主线程执行完毕后,子线程即自动结束。
e、锁
多个线程在操作同一个变量时,需要加锁操作,避免导致数据异常,在操作完毕后再进行解锁。
可以使用lock.acquire()和lock.release()方法来操作加、解锁。
也可以使用with lock:的方式,当该代码块执行时会自动加锁,执行完毕后会自动解锁。
※加、解锁务必一一对应,避免造成进程死锁
f、线程池、队列
需要安装threadpool模块
队列用于暂时存储数据,先进先出,队列在数据取出后即销毁该数据。主要用于异步化处理,且可以保证数据顺序。
使用队列时,需声明queue模块,然后orders_q = queue.Queue()实例化一个队列。
之后使用orders_q.put(order_id)方法来插入数据,以及oreder_id = orders_q.get()方法取出数据
#队列 list
importqueueimportrandomimporttimeimportthreading
orders_q=queue.Queue()#生产者/消费者模式
defproducer():for i in range(100):
order_id= random.randint(1, 99999)print('订单生成,orderid:%s'%order_id)
orders_q.put(order_id)
time.sleep(1)defconsumer():whileTrue:if orders_q.qsize()>0:
oreder_id=orders_q.get()print('consumer1,订单落库',oreder_id)
t= threading.Thread(target=producer)
t.start()
t= threading.Thread(target=consumer)
t.start()
2.09.30多线程
1、多线程、多进程
cpu密集型任务:
消耗cpu比较多
排序、运算。。
io密集型任务
input/output
写文件、读文件
上传、下载
队列
1、异步处理
2、保证顺序
并发:
100
8 c 同时最多只能运行8个任务