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——生产者消费者模型、线程的更多相关文章

  1. 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程

    进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...

  2. python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02

    目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...

  3. 生产者-消费者模型-线程安全队列Queue

    #python3 #product new data into the queue #comsume data from the queue from queue import Queue impor ...

  4. 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操

    昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...

  5. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  6. python_way ,day11 线程,怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)

    python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...

  7. Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

    Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...

  8. Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型

    http://blog.csdn.net/a352193394/article/details/39503857  Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...

  9. 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼

    1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...

随机推荐

  1. zzulioj - 2628: 小新的字母广场

    题目链接:http://acm.zzuli.edu.cn/problem.php?id=2628 题目描述        放假了,小新决定出去散散心,于是他来到了著名的字母广场.这个广场是由n*m块砖 ...

  2. 在windows环境下可以裁剪.jpg格式的图片

    发现在windows操作系统下,可以利用图片编辑器裁剪.jpg格式的尺寸大小.其四方有四个推子.可以移动.注意点击右方的“确定”按钮.

  3. nRF51822 Beacon 扫描请求包的设置

    Nordic 公司自己做有 iBeacon的板子和 SDK,很少有人拥有这个SDK,我最近在朋友那也拿到了一个,但是还没有时间看. 现在我们用普通的SDK自带的 Beacon 例程来做开发,开发的时相 ...

  4. eclipse juno 怎么安装maven

    步骤如下: 1.下载maven的bin,在apache官方网站可以下载. 2.下载下来之后,解压,找个路径放进去, 把bin的位置设在环境变量里,新建环境变量MAVEN_HOME. 3.在PATH里加 ...

  5. SDN阅读作业(二)

    前言碎碎念 当我看到这个全英论文以后,身体和心理都出现了戒断反应,让人无比难受,毕竟自己很久没做过英语阅读理解了.总之,在舍友大佬的帮助下以及各款翻译软件的鼎力支持之下(通篇读完后还是找了中文文献来对 ...

  6. SRS之安装与使用

    1. 安装 1.1 github 获取源码 git clone https://github.com/ossrs/srs.git 1.2 编译 1.2.1 关闭防火墙和 selinux 先关闭防火墙, ...

  7. .sql文件l通过PLSQL导入到Oracle数据库

    最近从第三方共享到一个数据,对方提供的是.sql文件.如何导入Oracle数据库? 开始想通过navicat for mysql工具--运行SQL文件来导入表---总是出现错误,失败. 后来还是用回P ...

  8. android -------- GifImageView 之gif图片加载

    目前支持Gif播放的开源库还是有的,试了一下还是这种好用点,所以来分享下android-gif-drawable是通过JNI来渲染帧的,这种方式比使用WebView或者Movie效率要高 要求Andr ...

  9. <img>的title和Alt有什么区别?

    Alt是<img>的特有属性,是图片内容的等价描述,用于图片无法加载时显示,读屏器阅读图片. title 可提高图片高可访问性,除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析.鼠 ...

  10. react前端模版Material-UI.类似于antd/bootstrap

    Material-UI Material-UI是一个实现了Google's Material Design设计规范的react组件库,开箱即用,使用它可以快速搭建出赏心悦目的应用界面. 文档 各种模版 ...