• 开启进程的两种方式——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)的更多相关文章

  1. Python 3 并发编程多进程之守护进程

    Python 3 并发编程多进程之守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemo ...

  2. python_并发编程——多进程的第二种启动方式

    1.多进程的第二种启动方式 import os from multiprocessing import Process # 创建一个自定义类,继承Process类 class MyProcess(Pr ...

  3. python网络编程之开启进程的方式

    标签(空格分隔): 开启进程的方式 multiprocessing模块介绍: python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在pyth ...

  4. python并发编程基础之守护进程、队列、锁

    并发编程2 1.守护进程 什么是守护进程? 表示进程A守护进程B,当被守护进程B结束后,进程A也就结束. from multiprocessing import Process import time ...

  5. Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型

    一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...

  6. python并发编程&多进程(二)

    前导理论知识见:python并发编程&多进程(一) 一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_cou ...

  7. python并发编程&多进程(一)

    本篇理论居多,实际操作见:  python并发编程&多进程(二) 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行) ...

  8. Python 3 并发编程多进程之队列(推荐使用)

    Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...

  9. python 并发编程 多进程 目录

    python multiprocessing模块 介绍 python 开启进程两种方法 python 并发编程 查看进程的id pid与父进程id ppid python 并发编程 多进程 Proce ...

随机推荐

  1. Python学习笔记-day1(if流程控制)

    在python中,流程控制语句为强制缩进(4空格) if username=='lmc' and password=='123456': print('Welcome User {name} logi ...

  2. raw_input功能

    摘要: raw_input()  &  input() raw_input的功能是方便的从控制台读入数据.  input与raw_input都是Python的内建函数,实现与用户的交互,但是功 ...

  3. 如何在InstallShield的MSI工程中调用Merge Module的Custom Action

    使用InstallShield创建了合并模块安装程序,定义自定义活动,可如何调用却不太清楚,网上也就找到这点信息,还是没有成功,到底该在什么地方执行合并模块的自定义活动? http://1662487 ...

  4. 流媒体 5——MPEG声音

    1. 听觉系统的感知特性: MPEG声音的数据压缩和编码不是依据波形本身的相关性和模拟人的发音器官的特性,而是利用人的听觉系统的特性来达到压缩声音数据的目的,这种压缩编码称为感知声音编码. 许多科学工 ...

  5. FW 数据库迁移之从oracle 到 MySQL

    方式一: 手动方式导入导出 手动的方式导入, 就是操作步骤会比较繁琐一些. 对Table 的结构和数据: 1. 使用 SQL Developer 把 oracle 的 table 的schema 和 ...

  6. python_71_json序列化1

    #序列化:序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程. #本例把字典数据类型存成字符串存在硬盘 #文件只能存字符串和二进制码,字典之类的不可以 info={ ...

  7. 数组逆序=全局内存版 VS 共享内存版

    全局内存版 #include <stdio.h> #include <assert.h> #include "cuda.h" #include " ...

  8. LigerUi中表(Grid)控件的相关属性笔记

    http://blog.csdn.net/dxnn520/article/details/8216560 // ========================================= [每 ...

  9. 线段树和zkw线段树

    作者作为一个蒟蒻,也是最近才自学了线段树,不对的地方欢迎大佬们评论,但是不要喷谢谢 好啦,我们就开始说说线段树吧 线段树是个支持区间操作和查询的东东,平时的话还是蛮实用的 下面以最基本的区间加以及查询 ...

  10. SpringBoot日志输出至Logstash

    1.springboot项目pom.xml文件下添加如下配置 2.resources目录下创建logback-spring.xml文件 <?xml version="1.0" ...