目录

  • Day 33 并发编程3

    • 生产者消费者模型

      • 要解决什么问题
      • 用途
    • 多线程
      • 什么是线程
      • 进程对比线程
      • 为什么用线程
      • 使用线程
      • 线程安全问题
      • 守护线程
      • 线程中的常用方法

Day 33 并发编程3

生产者消费者模型

模型就是解决某个问题的固定方法或者套路

要解决什么问题

  • 生产者:泛指生产数据的一方
  • 消费者:负责把处理数据的一方

案例:

​ 食堂饭店是生产者

​ 吃饭的人是消费者

他们之间的问题:

​ 效率低,因为双方的处理速度不一致,双方需要相互等待

具体的解决方案

  1. 先将双方解开耦合,让不同的进程负责不同的任务
  2. 提供一个共享容器,来平衡双方的能力,之所以用进程队列是因为队列可以在进程间共享

案例

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()

用途

常用来做流量削峰,保证服务不会因为高并发而崩溃

多线程

什么是线程

进程是操作系统可以调度和资源分配的基本单位,是一个资源单位,其中包含了运行这个程序所需的资源

线程是操作系统可以运算调度的最小单位,是真正的执行单位,一个线程就是一条固定的控制流程

一个进程可以包含多个线程,统一进程中的线程共享进程内的资源

系统会为每一个进程自动创建一条线程,称之为主线程,后续通过代码开启的线程称之为子线程

进程对比线程

进程是一个资源单位 而线程是执行单位

创建进程的开销大于线程

多个进程之间的内存是相互隔离的,而线程是共享进程内的所有资源

进程间是竞争关系,而线程间是合作关系

开启线程也需要消耗资源

进程之间有子父级关系

为什么用线程

  1. 有多个任务要并发处理
  2. 当要并发处理的任务有很多的时候,不能使用进程,进程资源开销大

使用线程

方式一:直接实例化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相关推荐

  1. 学习笔记(33):Python网络编程并发编程-进程池线程池

    立即学习:https://edu.csdn.net/course/play/24458/296451?utm_source=blogtoedu 进程池与线程池: 一般应用在网站上,进程池或线程池最大的 ...

  2. Java并发编程71道面试题及答案

    Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...

  3. Java并发编程73道面试题及答案——稳了

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户 ...

  4. 并发编程下的性能定律(翻译)

    并发编程下的性能定律(翻译) 理解Amdahl定律 如果你想利用多核的优势在尽可能少的时间运行尽可能多的指令,那么就需要以并行的序列分离代码.然而,大多的算法需要运行一些串行代码来调整并行执行.例如, ...

  5. Java并发编程71道面试题及答案 1

    1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...

  6. Java并发编程:CopyOnWrite容器的实现

    Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...

  7. Java并发编程75道面试题及答案

    1.在java中守护线程和本地线程区别?java中的线程分为两种:守护线程(Daemon)和用户线程(User).任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bo ...

  8. Java 高并发_JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过!...

    JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过! 1.JPG (37.82 KB, 下载次数: 0) 2018-12-3 09:40 上传 2.JPG (28 ...

  9. 并发编程-04线程安全性之原子性Atomic包的4种类型详解

    文章目录 线程安全性文章索引 脑图 概述 原子更新基本类型 Demo AtomicBoolean 场景举例 原子更新数组 Demo 原子更新引用类型 Demo 原子更新字段类型 使用注意事项: Dem ...

最新文章

  1. 互联网协议 — L2TP 二层隧道协议
  2. java编写简单计算器_编写java程序简单计算器
  3. 战痕————道具系统介绍
  4. Light bulbs(上海icpc网络预选赛,差分离散化)
  5. oracle数据库之数据导入问题
  6. java struct工作原理_Struts2的工作原理(图解)详解
  7. Windows上安装运行 cnpm, 来代替 npm
  8. Integer.ParseInt()异常
  9. 数据库入门教程(SQL Server 2005)----概述
  10. 免费在线语音识别成文字
  11. mentohust配置
  12. 透彻理解超级电容的11个参数
  13. c语言s-next,memset_s - [ C语言中文开发手册 ] - 在线原生手册 - php中文网
  14. 短视频剪辑教程自学难吗?子苗教育
  15. Layui框架基本使用
  16. 嵌入式的应用领域、现状及未来趋势
  17. 总有个短信发来一行乱码_为什么手机短信变成乱码
  18. 后谷歌时代 GoogleAdsense申请攻略和新玩法
  19. 写一个简单的操作系统
  20. 序 - 算神码男人系列

热门文章

  1. nginx配置http、https访问,nginx指定ssl证书,阿里云腾讯云华为云设置nginx https安全访问
  2. 2021-2027年中国智能马桶盖行业市场研究及前瞻分析报告
  3. etcd 笔记(03)— etcd 客户端使用(键值的增、删、改、查)、watch监测键、lease使用(创建租约、撤销租约、刷新租期、查询租期)
  4. Git 常用操作(2)- 创建标签
  5. git原理及常见使用方法
  6. leetcode 438. Find All Anagrams in a String 滑动窗口法
  7. Java集合之并发容器
  8. TVM在ARM GPU上优化移动深度学习
  9. 2021年大数据ZooKeeper(三):Zookeeper数据模型和节点类型
  10. Python的WeRoBot框架开发公众号