• 开启进程的两种方式——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. GBase数据库存储过程——批量删除多个数据表的数据

    偶尔需要清空一下数据库,重装成本太高. --清空历史存储过程 DROP Procedure `dap_model`.`delete_datas` ; --创建存储过程 DELIMITER // CRE ...

  2. linux 命令——7 mv(转)

    mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 1.命令格式: mv [选项] 源文件或目 ...

  3. noip模拟赛#39

    昨晚打开的题想了一会发现都不会后决定慢慢想.然后早上开校会的时候莫名其妙的都想出来了... T1:m=100,ai=50000,i<=5.1到m的数每个数只能用一次,判断是否能够有这些数的某些数 ...

  4. 第十六篇、OC_按比例适配

    // 屏幕高度 #define XMGHeight [UIScreen mainScreen].bounds.size.height // 屏幕宽度 #define XMGWidth [UIScree ...

  5. 第17题:打印1到最大的n位数

    面试题17:打印1到最大的n位数  题目:输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则打印出1.2.3一直到最大的3位数即999. 考点: 用字符串或者数组表达一个大数. 思路 1. ...

  6. BZOJ2118: 墨墨的等式(最短路 数论)

    题意 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. So ...

  7. Java 替换word文档文字,指定位置插入图片

    先说下 需要的依赖包 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ex ...

  8. ElasticSearch部署问题

    以下几个是以前在自己部署ElaticSearch的时候收集到的,认为有用的 https://my.oschina.net/topeagle/blog/591451?fromerr=mzOr2qzZ h ...

  9. yum安装报错

    检查了好久才知道原来是 sudo nano /etc/sysconfig/network-scripts/ifcfg-ens33 下的DNS配错了,改好之后,sudo service network ...

  10. nginx安装php环境

    1.php下载地址 https://secure.php.net/downloads.php(此次安装版本为7.0.33) 2.安装依赖的包 yum -y install libxml2 yum -y ...