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. Lightning Web Components 来自salesforce 的web 组件化解决方案

    Lightning Web Components 是一个轻量,快速,企业级别的web 组件化解决方案,官方网站也提供了很全的文档 对于我们学习使用还是很方便的,同时我们也可以方便的学习了解salesf ...

  2. Linux桌面最轻量的Dock之Plank介绍

    官方的文档描述 Plank 是“这个星球上最简洁的 dock”.该项目的目的就是仅提供一个 dock 需要的功能,尽管这是很基础的一个库,却可以被扩展,创造其他的含更多高级功能的 dock 程序. 这 ...

  3. Connection to newtaotao failed. [08001] Could not create connection to database

    jdbc.url=jdbc:mysql://localhost:3306/newtaotao?serverTimezone=UTC&characterEncoding=utf-8 数据库是5. ...

  4. mysql 获取数学成绩最高以及最低的同学

    mysql> select * from test; +----+----------+-------+-----------+ | id | name | score | subject | ...

  5. QML学习(三)——<QML命名规范>

    QML对象声明 QML对象特性一般使用下面的顺序进行构造: id 属性声明 信号声明 JavaScript函数 对象属性 子对象 状态 状态切换 为了获取更好的可读性,建议在不同部分之间添加一个空行. ...

  6. 百度地图中如何获取到发布的SHA1

    百度地图中如何获取到发布的SHA1 下面介绍的是一种通过命令的方式获取到发布版SHA1的方法: 打开Android的命令行Terminal: 1.首先进入到.android文件所在的目录,我的是如下图 ...

  7. 2019 SDN第一次阅读作业

    目录 阅读 文章链接 阅读 阅读文章<软件定义网络(SDN)研究进展>,并根据所阅读的文章,书写一篇博客,回答以下问题(至少3个): 1.为什么需要SDN?SDN特点? 背景:传统网络的层 ...

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

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

  9. 数据库sql优化总结之3--SQL优化总结

    SQL是每个Java程序员必回的一项技能,  对于项目中的各种复杂业务, 你是否能写出高效率, 简洁的SQL对于项目的运行效率和稳定性是有非常大的作用的. 通过个人的理解和网上的资料总结了一下常见的S ...

  10. jmeter测试 flask 接口请求

    jmeter测试 flask 接口请求 flask的代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Flas ...