day35——生产者消费者模型、线程
day35
进程:生产者消费者模型
编程思想,模型,设计模式,理论等等,都是交给你一种编程的方法,以后你遇到类似的情况,套用即可
生产者消费者模型的三要素
- 生产者:产生数据的
- 消费者:接收数据做进一步处理的
- 容器:盆(队列)
队列容器起到什么作用?
- 起到缓冲的作用,平衡生产力与消费力,解耦
from multiprocessing import Process
from multiprocessing import Queue
import time
import random
def producer(q, name):
for i in range(1,6):
time.sleep(random.randint(1, 2))
res = f"{i}号包子"
q.put(res)
print(f"生产者{name} 生产了{res}")
def consumer(q, name):
while 1:
try:
food = q.get(timeout=3)
time.sleep(random.randint(1, 3))
print(f'\033[31;0m消费者{name} 吃了{food}\033[0m')
except Exception:
return
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q, "孙宇"))
p2 = Process(target=consumer, args=(q, "海狗"))
p1.start()
p2.start()
线程的理论知识
什么是线程
一条流水线的工作流程
进程:在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用cpu去执行这些代码
之前的描述不够具体:
开启一个进程:在内存中开启一个进程空间,然后将主进程的所有的资源数据复制一份,然后调用线程去执行代码
进程是最小的资源单位,线程是最小的执行单位
以后你描述开启一个进程:
开启一个进程:进程会在内存中开辟一个进程空间,将主进程的资料数据全部复制一份,线程会执行里面的代码
线程vs进程
- 开启进程的开销非常大,比开启线程的开销大很多
- 开启线程的速度非常快,要快几十倍到上百倍
- 线程与线程之间可以共享数据,进程与进程之间需借助队列等方法实现通信
线程的应用
并发:一个cpu看起来像是同时执行多个任务
单个进程开启三个线程,并发的执行任务
开启三个进程并发的执行任务
文本编辑器:
1、输入文字
2、在屏幕上显示
3、保存在磁盘中
开启多线程就非常好了:数据共享、开销小、速度快
线程没有地位之分,但是一个进程谁在干活?
只是我们自己的意思:我们把执行主程序的线程当作主线程
主线程在执行代码,当结束之后,你得等待其他线程结束之后,才能结束本进程
开启线程的两种方式
# 第一种方式
from threading import Thread
import time
def task(name):
print(f"{name} is running")
time.sleep(1)
print(f"{name} is gone")
if __name__ == '__main__':
t1 = Thread(target=task, args=("海狗",))
t1.start()
print("===主线程") # 线程是没有主次之分的
# 第二种方式
from threading import Thread
import time
class MyThread(Thread):
def __init__(self, name, l1, s1):
super().__init__()
self.name = name
self.l1 = l1
self.s1 = s1
def run(self):
print(f"{self.name} is running")
time.sleep(1)
print(f"{self.name} is gone")
if __name__ == '__main__':
t1 = MyThread("李业", [1,2,3], "180")
t1.start()
print("===主线程")
线程vs进程的代码对比
开启速度对比
多线程
from threading import Thread
import time
def task():
print("hello")
if __name__ == '__main__':
start_time = time.time()
# 在主进程下开启线程
t1 = Thread(target=task)
t2 = Thread(target=task)
t1.start()
t2.start()
print("主线程/主进程")
print(time.time() - start_time)
时间:0.0004723072052001953
多进程
from multiprocessing import Process
import time
def work():
print("hellow")
if __name__ == '__main__':
start_time = time.time()
# 在主进程下开启线程
p1 = Process(target=work)
p2 = Process(target=work)
p1.start()
p2.start()
print("主线程/主进程")
print(time.time() - start_time)
时间:0.023804903030395508
对比pid
进程
主进程和每个子进程的pid都不一样
from multiprocessing import Process
import os
def task():
print(f"子进程:{os.getpid()}")
print(f"主进程:{os.getppid()}")
if __name__ == '__main__':
p1 = Process(target=task) # 创建一个进程对象
p2 = Process(target=task) # 创建一个进程对象
p1.start()
p2.start()
print(f"==主{os.getpid()}")
结果:
==主12832
子进程:14176
主进程:12832
子进程:11756
主进程:12832
线程
只要是在一个进程内,主线程和每个线程都一样
from threading import Thread
import os
def task():
print(os.getpid())
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task)
t1.start()
t2.start()
print(f"===主线程{os.getpid()}")
结果:
14480
14480
===主线程14480
同一个进程内线程共享内部数据
from threading import Thread
x = 3
def task():
global x
x = 100
if __name__ == '__main__':
t1 = Thread(target=task)
t1.start()
t1.join()
print(f"===主进程{x}")
线程的相关其他方法(了解)
from threading import Thread
from threading import activeCount
from threading import currentThread
from threading import enumerate
import os
import time
# x = 3
def task():
# print(currentThread()) # 获取当前线程对象
# time.sleep(1)
print(333)
if __name__ == '__main__':
t1 = Thread(target=task, name="线程1")
# t2 = Thread(target=task, name="线程2")
t1.start()
# t1.setName("朱凡宇") # 添加name属性
# print(t1.getName()) # 查看name属性
# print(t1.name) # 查看name属性 ****
# print(t1.isAlive()) # 判断线程是否活着
# threading方法
# print(currentThread()) # 获取当前线程对象
# print(enumerate()) # 返回一个列表,包含所有的线程对象
print(activeCount()) # 返回存活线程的数量 ****
# t2.start()
join与守护进程(考点)
join:阻塞 告知主线程要等待我子线程执行完毕之后再执行下面的代码
from threading import Thread
import time
def task(name):
print(f"{name} is running")
time.sleep(1)
print(f"{name} is gone")
if __name__ == '__main__':
start_time = time.time()
t1 = Thread(target=task, args=("海狗1",))
t2 = Thread(target=task, args=("海狗2",))
t3 = Thread(target=task, args=("海狗3",))
t1.start()
t1.join()
t2.start()
t2.join()
t3.start()
t3.join()
print(f"===主线程{time.time() - start_time}")
结果:
海狗1 is running
海狗1 is gone
海狗2 is running
海狗2 is gone
海狗3 is running
海狗3 is gone
===主线程3.0027503967285156
守护进程
# 守护进程
from multiprocessing import Process
import time
def foo():
print(123)
time.sleep(1)
print("end123")
def bar():
print(456)
time.sleep(2)
print("end456")
if __name__ == '__main__':
p1 = Process(target=foo)
p2 = Process(target=bar)
p1.daemon = True
p1.start()
p2.start()
print("===主")
结果:
===主
456
end456
守护线程
守护线程:如果守护线程的生命周期小于其他线程,则他肯定结束,否则等待其他非守护线程和主线程结束之后结束
# 单线程
from threading import Thread
import time
def sayhi(name):
# print("你滚!")
time.sleep(2)
print(f"{name} say hello")
if __name__ == '__main__':
t = Thread(target=sayhi, args=("egon",))
t.daemon = True
t.start()
print("主线程")
结果:
主线程
# 多线程一
from threading import Thread
import time
def foo():
print(123)
time.sleep(1)
print("end123")
def bar():
print(456)
time.sleep(3)
print("end456")
t1 = Thread(target=foo)
t2 = Thread(target=bar)
t1.daemon = True
t1.start()
t2.start()
print("main------------")
结果:
123
456
main------------
end123
end456
# 多线程二
from threading import Thread
import time
def foo():
print(123)
time.sleep(3)
print("end123")
def bar():
print(456)
time.sleep(1)
print("end456")
t1 = Thread(target=foo)
t2 = Thread(target=bar)
t1.daemon = True
t1.start()
t2.start()
print("main------------")
结果:
123
456
main------------
end456
互斥锁(考点)
问题
from threading import Thread
import time
import random
x = 100
def task():
# time.sleep(random.randint(1, 2))
global x
temp = x
time.sleep(random.randint(1, 3))
x = temp -1
if __name__ == '__main__':
l1 = []
for i in range(100):
t = Thread(target=task)
l1.append(t)
t.start()
for i in l1: # 使主线程无法先运行print(f"主线程{x}")
i.join()
print(f"主线程{x}")
结果: 一直是99
解决:
from threading import Thread
from threading import Lock
import time
import random
x = 100
def task(lock):
lock.acquire()
# time.sleep(random.randint(1, 2))
global x
temp = x
# time.sleep(random.randint(1, 3))
x = temp -1
lock.release()
if __name__ == '__main__':
mutex = Lock()
l1 = []
for i in range(100):
t = Thread(target=task, args=(mutex,))
l1.append(t)
t.start()
for i in l1: # 使主线程无法先运行print(f"主线程{x}")
i.join()
print(f"主线程{x}")
结果:一直是0
day35——生产者消费者模型、线程的更多相关文章
- 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程
进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...
- python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02
目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...
- 生产者-消费者模型-线程安全队列Queue
#python3 #product new data into the queue #comsume data from the queue from queue import Queue impor ...
- 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操
昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...
- 第23章 java线程通信——生产者/消费者模型案例
第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...
- python_way ,day11 线程,怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)
python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...
- Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)
Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...
- Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型
http://blog.csdn.net/a352193394/article/details/39503857 Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...
- 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼
1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...
随机推荐
- BZOJ 1034: [ZJOI2008]泡泡堂BNB 贪心+排序
比较神奇的贪心 有点类似于田忌赛马. 如果我方最弱强于对面最弱,则直接最弱pk最弱. 如果我方最强强于对面最强,那么直接最强间pk. 否则,试着用我方最弱 pk 对方最强,看是否能打成平手. code ...
- Windows异常分发函数---KiUserExceptionDispatcher
简介 KiUserExceptionDispatcher 是SEH分发器的用户模式的负责函数.当一个异常发生的时候,该异常将生成一个异常事件,内核检查该异常是否是由于执行用户模式代码导致的.如果是这样 ...
- 开源项目 10 CSV
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data; using Syst ...
- 从浏览器输入url到显示页面的过程 (前端面试题)
域名DNS解析,解析到真正的IP地址 | 客户端与服务端建立TCP连接,3次握手 | 客户端发送Http请求 | server接收到http请求,处理,并返回 | 客户端接收到 ...
- 平安寿险Java面试-社招-四面(2019/08)
个人情况 2017年毕业,普通本科,计算机科学与技术专业,毕业后在一个二三线小城市从事Java开发,2年Java开发经验.做过分布式开发,没有高并发的处理经验,平时做To G的项目居多.写下面经是希望 ...
- Spring Cloud Gateway(十一):全局过滤器GlobalFilter
本文基于 spring cloud gateway 2.0.1 1.简介 GlobalGilter 全局过滤器接口与 GatewayFilter 网关过滤器接口具有相同的方法定义.全局过滤器是一系列特 ...
- 基于Spring Boot+Cloud构建微云架构
前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而来,很多描述的重点也都偏向于作者自身碰到的问题,这样就很容易让你理解和操作出现偏差 ...
- slot 插槽子组件向父组件传值
slot 插槽要实现子组件向父组件传值,则需要运用 作用域插槽 1.父组件中用 标签加上 slot-scoped 的属性,属性值随性.(旧版本是scope,vue新版本必须用slot-scope) 2 ...
- PostgreSQL中的表连接操作
- 微信小程序开发——base64位图片显示问题
前言: 目前小程序项目需要后端借口提供验证码图片,后端是以base64位返回的,按照H5的做法,前边拼上 data:image/png;base64, 应该就可以了,关键代码如下: H5: <i ...