生产者消费者模型 与多线程(1)
生产者消费者模型
模型就是要解决某个问题的固定方法或套路
要解决的问题
生产者:泛指生产数据的一方
消费者:泛指处理数据的一方
双方的处理速度不一致,导致总有一方会在等待
解决问题的方法
- 先将双方解开耦合,让不同的进程负责不同的任务
- 提供一个共享的容器如队列,用来平衡双方的能力,用队列是因为队列可以在进程间共享
案例:
from multiprocessing import Process,Queue
import request
import re,os,time,random
#生产者任务
def product(urls,q):
i = 0
for url in urls:
response = requests.get(url)
text = response.text
#将生产完的数据放入队列中
time.sleep(random.random())
q.put(text)
i += 1
print(os.getpid(),'生产了第%s个数据'%i)
def customer(q):
i = 0
while True:
text = q.get()
time.sleep(random.random())
res = re.findall('src = //(.*?) width',text)
i += 1
print(f'第{i}个任务获取到{len(res)}个img')
if __name__ == '__main__':
urls = ["http://www.baidu.com",
"http://www.baidu.com",
"http://www.baidu.com",
"http://www.baidu.com"]
#创建一个双方能够共享的容器
q = Queue()
#生产者进程
p1 = Process(target=product,args=(urls,q))
p1.start()
#消费者进程
c = Process(target=customer,args=(q,))
c.start()
多线程
什么是线程
线程是操作系统可以运算调度的最小单位,是包含在线程中的真正的执行单位,一个线程就是一条固定的控制流程
一个进程可以包含多个线程,同一个进程中的线程共享进程内的资源,每个进程在开启的时候系统会自动为其创建一条线程称之为主线程,后续通过代码开启的线程都是子线程
线程和进程对比
进程是资源单位,线程是执行单位
创建进程的开销远大于线程
多个进程之间内存相互隔离,多个线程间内存共享进程内所有资源
进程之间对于硬件资源是竞争关系,而线程之间是协作关系
进程之间有层级关系,而线程之间没有,是平等的
使用线程的情况
当有多个任务要并发处理时
当要并发处理的任务有很多的时候,不能使用进程,因为进程资源开销太大,线程开销非常小,适用于任务数量非常多的情况
使用线程的两种方式
类似于进程的两种方式
1.实例化threading中的Thread类
2.继承Thread类,覆盖run方法,把要在子线程中执行的代码放入run方法中
线程安全问题
只要是使用公共资源都会产生数据安全问题,解决方法是给操作公共资源的代码加锁
守护线程
一个线程设置为另一个线程的守护线程,就会随着对方的结束而结束
默认情况下主线程代码执行完毕后会等待所有非守护线程完毕后结束而不管守护线程,大致意思就是:守护线程是被守护线程的舔狗,被守护线程是非守护线程的舔狗