Day 33 并发编程3
目录
- Day 33 并发编程3
- 生产者消费者模型
- 要解决什么问题
- 用途
- 多线程
- 什么是线程
- 进程对比线程
- 为什么用线程
- 使用线程
- 线程安全问题
- 守护线程
- 线程中的常用方法
- 生产者消费者模型
Day 33 并发编程3
生产者消费者模型
模型就是解决某个问题的固定方法或者套路
要解决什么问题
- 生产者:泛指生产数据的一方
- 消费者:负责把处理数据的一方
案例:
食堂饭店是生产者
吃饭的人是消费者
他们之间的问题:
效率低,因为双方的处理速度不一致,双方需要相互等待
具体的解决方案
- 先将双方解开耦合,让不同的进程负责不同的任务
- 提供一个共享容器,来平衡双方的能力,之所以用进程队列是因为队列可以在进程间共享
案例
from multiprocessing import Process,Queue
import requests,time,random,re,osdef product(urls,q):i=1for url in urls:respone=requests.get(url)text=respone.text# time.sleep(random.random())q.put(text)print(os.getpid(),f'got NO{i} info')i+=1def customer(q):i=1while True:text=q.get()time.sleep(random.random())res=re.findall('src=//(.*?) width', text)print(f'got NO{i} img')i++1if __name__ == '__main__':urls = ["http://www.baidu.com","http://www.baidu.com","http://www.baidu.com","http://www.baidu.com",]q=Queue()p=Process(target=product,args=(urls,q))p.start()c=Process(target=customer,args=(q,))c.start()
问题:customer进程不知道什么时候结束
joinableQueue继承自Queue,用法一致
增加了join和taskDone
join是一个阻塞函数,会阻塞直到taskdone的调用次数等于存入的元素个数,可以用于表示队列任务处理完成
from multiprocessing import Process,JoinableQueue
import requests,time,random,re,osdef product(q,name):for i in range(5):hot_dog=f'hot_dog{i+1} from {name}'time.sleep(random.random())q.put(hot_dog)print(f'{name} make hot_dog{i+1}')def customer(q):while True:hot_dog=q.get()time.sleep(random.random())print(f'eat {hot_dog}')q.task_done()if __name__ == '__main__':q=JoinableQueue()p1=Process(target=product,args=(q,'shanghai'))p1.start()p2=Process(target=product,args=(q,'beijing'))p2.start()c=Process(target=customer,args=(q,))c.start()p1.join()p2.join()q.join()c.terminate()
用途
常用来做流量削峰,保证服务不会因为高并发而崩溃
多线程
什么是线程
进程是操作系统可以调度和资源分配的基本单位,是一个资源单位,其中包含了运行这个程序所需的资源
线程是操作系统可以运算调度的最小单位,是真正的执行单位,一个线程就是一条固定的控制流程
一个进程可以包含多个线程,统一进程中的线程共享进程内的资源
系统会为每一个进程自动创建一条线程,称之为主线程,后续通过代码开启的线程称之为子线程
进程对比线程
进程是一个资源单位 而线程是执行单位
创建进程的开销大于线程
多个进程之间的内存是相互隔离的,而线程是共享进程内的所有资源
进程间是竞争关系,而线程间是合作关系
开启线程也需要消耗资源
进程之间有子父级关系
为什么用线程
- 有多个任务要并发处理
- 当要并发处理的任务有很多的时候,不能使用进程,进程资源开销大
使用线程
方式一:直接实例化thread类
方式二:继承thread类
from threading import Threaddef task():print('son run')t=Thread(target=task) #子线程不需要重新读取主线程的代码 所以开启线程的代码可以随便放在需要的位置
t.start()
print('over')
# 线程开启速度快 所以先打印son run 后打印overclass MyThread(Thread):def run(self) -> None:print(' son run')t=MyThread()
t.start()
print('over')
线程安全问题
线程并发访问了同一资源一定会产生安全问题,解决方案和进程一样,就是给公共资源加锁
from threading import Thread,Lock
import timel=Lock()
a=10def task():global al.acquire()time.sleep(1)a-=1print(a)l.release()for i in range(10):t=Thread(target=task)t.start()print(f'{i} work')
# 瞬间开启10个线程,但是同一时间只有1个线程可以执行函数代码
守护线程
一个线程a设置为b的守护线程,a会随着b的结束而结束
默认情况下主线程代码执行完毕,也会等待所有子线程执行完毕后才能结束,因为多个线程之间是协作关系
from threading import Thread,Lock
import timedef task1():print('this is taks1')time.sleep(5)print('task1 going to die')def task2():print('this is task2')time.sleep(4)print('task2 not dead')print('main will be dead in 3 seconds')
t1=Thread(target=task1)
t1.daemon=True
t1.start()
t2=Thread(target=task2)
t2.daemon=False
t2.start()time.sleep(1)
print('main dead')
线程中的常用方法
from threading import Thread,currentThread,enumerate,activeCount
import time# t = Thread()
# t.start()
# t.join()
# t.is_alive()
# t.isAlive()
# t.ident # 线程标识符 id
# t.daemon# 获取当前线程对象
# print(currentThread())
# t = Thread(target=lambda :print(currentThread()))
# t.start()t = Thread(target=lambda :time.sleep(1))
t.start()t = Thread(target=lambda :time.sleep(1))
t.start()
t.join()
# 获取正在运行的所有线程对象 是一个列表
print(enumerate())# 存活的线程数量
print(activeCount())
转载于:https://www.cnblogs.com/masterjian924/p/11134793.html
Day 33 并发编程3相关推荐
- 学习笔记(33):Python网络编程并发编程-进程池线程池
立即学习:https://edu.csdn.net/course/play/24458/296451?utm_source=blogtoedu 进程池与线程池: 一般应用在网站上,进程池或线程池最大的 ...
- Java并发编程71道面试题及答案
Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...
- Java并发编程73道面试题及答案——稳了
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户 ...
- 并发编程下的性能定律(翻译)
并发编程下的性能定律(翻译) 理解Amdahl定律 如果你想利用多核的优势在尽可能少的时间运行尽可能多的指令,那么就需要以并行的序列分离代码.然而,大多的算法需要运行一些串行代码来调整并行执行.例如, ...
- Java并发编程71道面试题及答案 1
1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...
- Java并发编程:CopyOnWrite容器的实现
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- Java并发编程75道面试题及答案
1.在java中守护线程和本地线程区别?java中的线程分为两种:守护线程(Daemon)和用户线程(User).任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bo ...
- Java 高并发_JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过!...
JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过! 1.JPG (37.82 KB, 下载次数: 0) 2018-12-3 09:40 上传 2.JPG (28 ...
- 并发编程-04线程安全性之原子性Atomic包的4种类型详解
文章目录 线程安全性文章索引 脑图 概述 原子更新基本类型 Demo AtomicBoolean 场景举例 原子更新数组 Demo 原子更新引用类型 Demo 原子更新字段类型 使用注意事项: Dem ...
最新文章
- 互联网协议 — L2TP 二层隧道协议
- java编写简单计算器_编写java程序简单计算器
- 战痕————道具系统介绍
- Light bulbs(上海icpc网络预选赛,差分离散化)
- oracle数据库之数据导入问题
- java struct工作原理_Struts2的工作原理(图解)详解
- Windows上安装运行 cnpm, 来代替 npm
- Integer.ParseInt()异常
- 数据库入门教程(SQL Server 2005)----概述
- 免费在线语音识别成文字
- mentohust配置
- 透彻理解超级电容的11个参数
- c语言s-next,memset_s - [ C语言中文开发手册 ] - 在线原生手册 - php中文网
- 短视频剪辑教程自学难吗?子苗教育
- Layui框架基本使用
- 嵌入式的应用领域、现状及未来趋势
- 总有个短信发来一行乱码_为什么手机短信变成乱码
- 后谷歌时代 GoogleAdsense申请攻略和新玩法
- 写一个简单的操作系统
- 序 - 算神码男人系列
热门文章
- nginx配置http、https访问,nginx指定ssl证书,阿里云腾讯云华为云设置nginx https安全访问
- 2021-2027年中国智能马桶盖行业市场研究及前瞻分析报告
- etcd 笔记(03)— etcd 客户端使用(键值的增、删、改、查)、watch监测键、lease使用(创建租约、撤销租约、刷新租期、查询租期)
- Git 常用操作(2)- 创建标签
- git原理及常见使用方法
- leetcode 438. Find All Anagrams in a String 滑动窗口法
- Java集合之并发容器
- TVM在ARM GPU上优化移动深度学习
- 2021年大数据ZooKeeper(三):Zookeeper数据模型和节点类型
- Python的WeRoBot框架开发公众号