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. BZOJ 1034: [ZJOI2008]泡泡堂BNB 贪心+排序

    比较神奇的贪心 有点类似于田忌赛马. 如果我方最弱强于对面最弱,则直接最弱pk最弱. 如果我方最强强于对面最强,那么直接最强间pk. 否则,试着用我方最弱 pk 对方最强,看是否能打成平手. code ...

  2. Windows异常分发函数---KiUserExceptionDispatcher

    简介 KiUserExceptionDispatcher 是SEH分发器的用户模式的负责函数.当一个异常发生的时候,该异常将生成一个异常事件,内核检查该异常是否是由于执行用户模式代码导致的.如果是这样 ...

  3. 开源项目 10 CSV

    using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data; using Syst ...

  4. 从浏览器输入url到显示页面的过程 (前端面试题)

    域名DNS解析,解析到真正的IP地址             | 客户端与服务端建立TCP连接,3次握手 | 客户端发送Http请求 | server接收到http请求,处理,并返回 | 客户端接收到 ...

  5. 平安寿险Java面试-社招-四面(2019/08)

    个人情况 2017年毕业,普通本科,计算机科学与技术专业,毕业后在一个二三线小城市从事Java开发,2年Java开发经验.做过分布式开发,没有高并发的处理经验,平时做To G的项目居多.写下面经是希望 ...

  6. Spring Cloud Gateway(十一):全局过滤器GlobalFilter

    本文基于 spring cloud gateway 2.0.1 1.简介 GlobalGilter 全局过滤器接口与 GatewayFilter 网关过滤器接口具有相同的方法定义.全局过滤器是一系列特 ...

  7. 基于Spring Boot+Cloud构建微云架构

    前言 首先,最想说的是,当你要学习一套最新的技术时,官网的英文文档是学习的最佳渠道.因为网上流传的多数资料是官网翻译而来,很多描述的重点也都偏向于作者自身碰到的问题,这样就很容易让你理解和操作出现偏差 ...

  8. slot 插槽子组件向父组件传值

    slot 插槽要实现子组件向父组件传值,则需要运用 作用域插槽 1.父组件中用 标签加上 slot-scoped 的属性,属性值随性.(旧版本是scope,vue新版本必须用slot-scope) 2 ...

  9. PostgreSQL中的表连接操作

  10. 微信小程序开发——base64位图片显示问题

    前言: 目前小程序项目需要后端借口提供验证码图片,后端是以base64位返回的,按照H5的做法,前边拼上 data:image/png;base64, 应该就可以了,关键代码如下: H5: <i ...