并发编程——多进程——multiprocessing开启进程的方式及其属性(3)
- 开启进程的两种方式——Process
- 方式一:函数方法
from multiprocessing import Process
import time
def task(name):
print('%s is running'%name)
time.sleep(3)
print('%s is done' % name)
if __name__ == '__main__':
p = Process(target=task,args=('子进程1',))
p.start() #仅仅只是给操作系统发送了一个信号 print('主进程')方式一
- 方式二:类方法
from multiprocessing import Process
import time,os
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
print('%s is running'%self.name,os.getppid())
time.sleep(3)
print('%s is done' % self.name,os.getppid())
if __name__ == '__main__':
p = MyProcess('子进程1')
p.start() print('主进程',os.getpid())方式二
- 进程id
- 子进程id : os.getpid()
- 父进程id : os.getppid()
- 僵尸进程与孤儿进程(仅存在于linux和unix系统中)
- 僵尸进程:在Linux系统中,任何子进程都会经历僵尸进程模式,以便父进程查看子进程状态,pid不会丢失,占用pid资源,在父进程一直不死的情况下有害
- 孤儿进程:父进程已死,子进程依然活着;孤儿进程会被一个INIT进程收留,是无害的。
- Process的方法介绍
- p.start():启动进程,并调用该子进程中的p.run()
- p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
- p.is_alive():如果进程p仍然运行,返回True
- p.join([timeout]):主进程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout 是可选的超时时间。
- p.name:查看子进程的进程名,即使子进程终止了,也可以查到
- join方法
def talk(name):
print("%s 开始说话"%name)
time.sleep(random.randint(1,5))
print("%s 说话结束" %name)
if __name__ == '__main__':
# freeze_support()
p1 = Process(target=talk,args=(1,))
p2 = Process(target=talk,args=(2,))
p3 = Process(target=talk,args=(3,))
p = [p1,p2,p3]
for i in p:
i.start()
# p1.terminate()
for i in p:
i.join() print("主进程结束")join方法
- join是主进程在等子进程结束,当有多个子进程时,子进程之间依然是并发的
- 守护进程
- 守护进程会在主进程代码执行结束后就终止,字随父死
- 守护进程内无法再开启子进程,否则抛出异常
#-*- coding:utf-8 -*-
import time
from multiprocessing import Process
def task(name):
print("子进程%s开始执行"%name)
time.sleep(2)
# p = Process(target=time.time,args=(3,))
# p.start()
print("子进程%s执行完毕"%name)
if __name__ == '__main__':
p = Process(target=task,args = (1,))
p.daemon = True
p.start()
# p.join()
print("主")守护进程
- 互斥锁
- 把并发变成串行,牺牲效率,保证数据的正确性
- 前提:共享同一套文件系统(存储于硬盘中)
- 存在的问题:效率低,需要自己加锁处理
#-*- coding:utf-8 -*-
from multiprocessing import Process,Lock
import os,time
def work(lock):
lock.acquire()#加锁
print('%s is running' %os.getpid())
time.sleep(2)
print('%s is done' %os.getpid())
lock.release()#释放锁 if __name__ == '__main__':
lock = Lock()
for i in range(3):
p=Process(target=work,args=(lock,))
p.start()互斥锁
- 与join的区别
- join是将一个任务整体串行
- 互斥锁:可以将一个任务中的某一段代码串行
# -*- coding:utf-8 -*-
import json
import time
from multiprocessing import Process,Lock def search(name):
time.sleep(1)
dic = json.load(open('db.txt','r',encoding='utf-8'))
print('<%s>查看到剩余票数[%s]' % (name, dic['count'])) def get(name,lock):
lock.acquire()
time.sleep(1)
dic = json.load(open('db.txt', 'r', encoding='utf-8'))
if dic['count'] > 0:
dic['count'] -= 1
time.sleep(3)
json.dump(dic, open('db.txt', 'w', encoding='utf-8'))
print('<%s>购票成功' % name)
lock.release() def task(name,lock):
search(name)
get(name,lock) if __name__ == '__main__':
lock = Lock() for i in range(1,10):
p = Process(target=task, args=(i,lock))
p.start()
# p.join()模拟抢票
- 队列
- 队列和管道都是将数据存放于内存中,而队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,因而队列才是进程间通信(IPC)的最佳选择
- 创建队列的类:Queue([maxsize])
- [maxsize]是队列中允许最大项数,省略则无大小限制
- 队列内存放的是消息而非大数据
- 队列占用的是内存空间,因而maxsize即便是无大小限制也受限于内存大小
#-*- coding:utf-8 -*-
from multiprocessing import Process,Queue
q = Queue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.full())
# q.put(4)#再放就阻塞了 print(q.get())
print(q.get())
print(q.get())
print(q.empty())#空了
# print(q.get())#再取就阻塞了队列
- 生产者消费者模型
- 什么是生产者消费者模型
- 生产者消费者模型是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列中取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
- 什么是生产者消费者模型
- 程序中有两类角色
- 一类负责生产数据(生产者)
- 一类负责处理数据(消费者)
- 引入生产者消费者模型是为了解决的问题是
- 平衡生产者与消费者之间的速度差
- 程序解开耦合
- 如何实现生产者消费者模型
- 生产者<--->队列<--->消费者
#-*- coding:utf-8 -*-
from multiprocessing import Process,Queue
import time
import random
import os
def consumer(q,name):
while True:
res = q.get()
if res is None:break
time.sleep(random.randint(1,3))
print('\033[43m%s 吃 %s\033[0m' %(name,res))
def producer(q,name,food):
for i in range(3):
time.sleep(random.randint(1,3))
res = '%s%s'%(food,i)
q.put(res)
print('\033[45m%s 生产了 %s\033[0m' % (name, res))
if __name__ == '__main__':
q = Queue()
#生产者们,即厨师
p1 = Process(target=producer,args=(q,'egon1','包子'))
p2 = Process(target=producer,args=(q,'egon2','骨头'))
p3 = Process(target=producer,args=(q,'egon3','饺子')) #消费者们:即吃货们
c1 = Process(target=consumer,args=(q,'alex1'))
c2 = Process(target=consumer,args=(q,'alex2')) #开始
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
p1.join()
p2.join()
p3.join()
q.put(None)
q.put(None)
q.put(None)
print('主程序结束')生产者消费者模型
- 程序中有两类角色
- JoinableQueue([maxsize])
- JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:
- q.task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
- q.join():生产者调用此方法进行阻塞,知道队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止。
#-*- coding:utf-8 -*-
from multiprocessing import Process,JoinableQueue
import time,random,os
def consumer(q,name):
while True:
res = q.get()
time.sleep(random.randint(1,3))
print('\033[43m%s 吃 %s\033[0m' %(name,res))
q.task_done()#发送信号给q.join(),说明已经从队列中取走一个数据并处理完毕了
def producer(q,name,food):
for i in range(3):
time.sleep(random.randint(1,3))
res = '%s%s'%(food,i)
q.put(res)
print('\033[45m%s 生产了 %s\033[0m' % (name, res))
q.join()#等到消费者把自己放入队列中的所有的数据都取走之后,生产者才结束 if __name__ == "__main__":
q = JoinableQueue()#使用JoinableQueue()
#生产者们:即厨师们
p1 = Process(target=producer, args=(q, 'egon1', '包子'))
p2 = Process(target=producer, args=(q, 'egon2', '骨头'))
p3 = Process(target=producer, args=(q, 'egon3', '泔水'))
# 消费者们:即吃货们
c1 = Process(target=consumer, args=(q, 'alex1'))
c2 = Process(target=consumer, args=(q, 'alex2'))
c1.daemon = True
c2.daemon = True
# 开始
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
p1.join()
p2.join()
p3.join()
#1、主进程等生产者p1、p2、p3结束
#2、而p1、p2、p3是在消费者把所有数据都取干净之后才会结束
#3、所以一旦p1、p2、p3结束了,证明消费者也没必要存在了,应该随着主进程一块死掉,因而需要将生产者们设置成守护进程
print('主')使用JoinableQueue实现消费者生产者模型
并发编程——多进程——multiprocessing开启进程的方式及其属性(3)的更多相关文章
- Python 3 并发编程多进程之守护进程
Python 3 并发编程多进程之守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemo ...
- python_并发编程——多进程的第二种启动方式
1.多进程的第二种启动方式 import os from multiprocessing import Process # 创建一个自定义类,继承Process类 class MyProcess(Pr ...
- python网络编程之开启进程的方式
标签(空格分隔): 开启进程的方式 multiprocessing模块介绍: python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在pyth ...
- python并发编程基础之守护进程、队列、锁
并发编程2 1.守护进程 什么是守护进程? 表示进程A守护进程B,当被守护进程B结束后,进程A也就结束. from multiprocessing import Process import time ...
- Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型
一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...
- python并发编程&多进程(二)
前导理论知识见:python并发编程&多进程(一) 一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_cou ...
- python并发编程&多进程(一)
本篇理论居多,实际操作见: python并发编程&多进程(二) 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行) ...
- Python 3 并发编程多进程之队列(推荐使用)
Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...
- python 并发编程 多进程 目录
python multiprocessing模块 介绍 python 开启进程两种方法 python 并发编程 查看进程的id pid与父进程id ppid python 并发编程 多进程 Proce ...
随机推荐
- Html+css实现带图标的控件
</pre><pre name="code" class="html"><!DOCTYPE html> <html l ...
- U盘小偷——C++实现U盘插入检测和文件扫描拷贝
前几天女朋友说老师上课的PPT不共享,没法复习,想着写个U盘小偷拷贝PPT来着,后来觉得这样的行为这是不对的,万一不小心复制了老师的专利啥的,或者一些不可描述的东西,就闹大了. 虽然没有采取实际行动, ...
- linux 命令——49 at (转)
在windows系统中,windows提供了计划任务这一功能,在控制面板 -> 性能与维护 -> 任务计划, 它的功能就是安排自动运行的任务. 通过'添加任务计划'的一步步引导,则可建立一 ...
- 300行ABAP代码实现一个最简单的区块链原型
不知从什么时候起,区块链在网上一下子就火了. 这里Jerry就不班门弄斧了,网上有太多的区块链介绍文章.我的这篇文章没有任何高大上的术语,就是300行ABAP代码,实现一个最简单的区块链原型. 我个人 ...
- select into outfile
语法格式如下: SELECT [列名] FROM table [WHERE 语句] INTO OUTFILE '目标文件' [OPTION]; FIELDS TERMINATED ...
- 【CF1000C】Covered Points Count(离散化+差分)
点此看题面 大致题意: 给出\(n\)条线段,分别求有多少点被覆盖\(1\)次.\(2\)次...\(n\)次. 正常的算法 好吧,这道题目确实有个很简单的贪心做法(只可惜我做的时候没有想到,结果想了 ...
- RAC基本使用
@interface ViewController () @property (weak, nonatomic) IBOutlet lwRedView *redView; @property (wea ...
- Python求包含数字或字母最长的字符串及长度
一.求包含数字或字母最长的字符串及长度 org = 'ss121*2222&sdfs2!aaabb' result = [] #保存最终要输出的字符串 result_temp = [] #保存 ...
- c++异常处理--创建自己的异常处理类
复习了一下c++中的异常处理! 继承exception类 class myException : public std::exception { public: explicit myExceptio ...
- django+xadmin在线教育平台(四)
3-2 配置表单页面 必要的该说的,该了解的 前置条件: 你已经学习了前面教程.将项目的文件夹目录结构,setting配置等修改完毕与我保持一致. 本节通过Django快速的配置一个留言板页面来学习 ...