多进程

作者: 程序员Darker | 来源:发表于2019-02-27 13:29 被阅读0次

什么是多任务?

同时运行多个程序,比如:一边下载视频,一边听歌,一边使用浏览器

进程

什么是进程

  • 计算机中已经运行程序的实体
  • 运行在内存中活的程序

什么是程序

存在硬盘中的死的二进制文件

进程调度

  • 时间片轮转:CPU给进程一个很小的时间段,程序交替执行
  • 并发:在同一时刻,只有一个进程在运行,交替运行,时间片轮转算法
  • 并行:在同一时刻,多个进程同时进行。

Linux中的fork

实例代码

  1. 注意:fork只可以在Linux下使用
  2. 语法代码
import os
# pid 是当前进程的子进程PID
# os.getpid()   是当前进程的进程号
# os.getppid()  是其父进程的进程号
# 子进程永远返回0,而父进程返回子进程的ID。
pid = os.fork()
if pid == 0:
    print("子进程")
    print(f"pid:{pid} 猜猜我会出现几次  当前进程号: {os.getpid()} 父进程:{os.getppid()}")
else:
    print("父进程")
    print(f"pid:{pid} 猜猜我会出现几次  当前进程号: {os.getpid()} 父进程:{os.getppid()}")
  1. 程序执行到os.fork()时,操作系统会创建一个新的进程(子进程),然后复制父进程的所有信息到子进程中。
  2. 父进程和子进程都会从fork()函数中得到一个返回值,在子进程中这个值一定是0,而父进程中是子进程的id号。

多进程修改全局变量

import os

a = 0

pid = os.fork()
if pid == 0:
    a += 1
    print(f"子进程:{a}")
else:
    a += 1
    print(f"父进程:{a}")

总结:多进程中,每个进程中所有数据(包括全局变量)都各有拥有一份,互不影响

多次fork问题

# coding=utf-8
import os
import time

# 注意,fork函数,只在Unix/Linux/Mac上运行,windows不可以  6
pid = os.fork()
if pid == 0:
    print('hello 1')
else:
    print('hello 2')

pid = os.fork()
if pid == 0:
    print('hello 3')
else:
    print('hello 4')

time.sleep(1)

注意:父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法

python多进程编程

Process类

import time
from multiprocessing import Process


def sing():
    for _ in range(5):
        print("唱歌")
        time.sleep(1)


def dance():
    for _ in range(5):
        print("跳舞")
        time.sleep(1)


def main():
    # 创建对象
    p1 = Process(target=sing)
    p2 = Process(target=dance)
    # 启动进程实例
    p1.start()
    p2.start()
    # 等待子进程结束
    p1.join()
    p2.join()



if __name__ == '__main__':
    # 开始时间
    time_start = time.time()
    main()
    # 结束时间
    time_end = time.time()
    print(f"总输出时间:{time_end-time_start}")

Process([group [, target [, name [, args [,kwargs]]]]])

  • target:表示这个进程实例所调用对象;
  • args:表示调用对象的位置参数元组;
  • kwargs:表示调用对象的关键字参数字典;
  • name:为当前进程实例的别名;
  • group:大多数情况下用不到;

Process类常用方法:

  • is_alive():判断进程实例是否还在执行;
  • join([timeout]):是否等待进程实例执行结束,或等待多少秒;
  • start():启动进程实例(创建子进程);
  • run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法;
  • terminate():不管任务是否完成,立即终止;

Process类常用属性:

  • name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数;
  • pid:当前进程实例的PID值;
    join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。

Process类继承

from multiprocessing import Process


class ProcessClass(Process):
    def __init__(self, name):
        # 直接调用父类的构造方法,下面两种方法都可以
        Process.__init__(self)
        # super(ProcessClass, self).__init__()
        # 初始化赋值
        self.name = name

    def run(self):
        print("我是Process类的继承", self.name)


# 创建一个子进程
p1 = ProcessClass("江小白")

# 启动子进程
p1.start()

进程池

import time
from multiprocessing.dummy import Pool


def work(num):
    print("当前num", num)
    time.sleep(1)


# 创建池子
p = Pool(5)
for i in range(30):
    p.apply_async(work, args=(i,))
# 关闭以后不可以再添加任务,但是以前的任务会执行完
p.close()
# 等待结束
p.join()

进程间通信

import time
from multiprocessing import Queue, Process


# 写入函数
def write(queue):
    # li = ['a', 'b', 'c', 'd', 'e', 'f']
    for i in ['a', 'b', 'c', 'd', 'e', 'f']:
        # 把i放到队列里
        queue.put(i)
        # print(f"把{i}放到队列中")
        print("把", i, "放到队列中")
        # 睡眠
        # time.sleep(1)


# 读出函数
def read(queue):
    while 1:
        print("读出:", queue.get(), "数量", queue.qsize())


# 创建队列
q = Queue(3)
# 创建进程
p1 = Process(target=write, args=(q,))
p2 = Process(target=read, args=(q,))
# 启动进程
p1.start()
p2.start()
# 等待进程
p1.join()
p2.join()

Queue的使用

  • Queue.qsize(): 返回当前队列包含的消息数量;
  • Queue.empty(): 如果队列为空,返回True,反之False ;
  • Queue.full(): 如果队列满了,返回True,反之False;
  • Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
    1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout ,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;
    2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;
    Queue.get_nowait():相当Queue.get(False);
  • Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True;
    1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;
    2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;
  • Queue.put_nowait(item):相当Queue.put(item, False);
    进程间的数据相互独立

其它补充

孤儿进程

就是父进程先于子进程死的时候,子进程就变成孤儿进程,会认1号进程为干爹

僵尸进程

子进程死了,父进程还没来得急给儿子收尸,子进程就会成为僵尸进程
如何清理僵尸进程:

  1. ps -ef | grep "def" 这个出来就是僵尸进程
  2. kill -9 父进程

杀死僵尸进程的父进程,僵尸进程就会变成孤儿进程

守护进程

当成为孤儿进程后,会被1号进程收养,这个孤儿进程将不会被结束掉,成为守护进程

相关文章

  • UNIX基础--进程和守护进程

    进程和守护进程 Processes and Daemons 进程(Processes) FreeBSD 是一个多任...

  • rsync服务企业应用

    守护进程服务企业应用: 守护进程多模块功能配置 守护进程的排除功能实践 守护进程来创建备份目录 守护进程的访问控制...

  • Nginx 的进程结构,你明白吗?

    Nginx 进程结构 这篇文章我们来看下 Nginx 的进程结构,Nginx 其实有两种进程结构: 单进程结构 多...

  • 进程/线程

    进程和线程 多任务的介绍 进程的介绍 多进程完成多任务 获取进程编号 进程的注意点 文件夹高并发copy器 1、多...

  • 多易日记进程

    10.29 解决移动端适配问题:采用手淘写的lib-flexible解决移动端的适配,采用pxToRem解决px转...

  • 使用ipc为 electron 实现一个无用的通信轮子

    入门学习electron时了解到,渲染进程与主进程存在一对多的关系, 渲染进程与主进程需要通过ipc或remote...

  • mysql(三)

    MySQL多实例 什么是实例? 一个进程+多个线程+预分配的内存结构 什么是多实例? 多个进程+多个线程+多个预分...

  • 线程和线程池

    线/进程、多线/多进程、线程并发/并行 一、线程、进程概念 进程:是程序的一次运行活动,由系统资源分配和调度的一个...

  • Python札记52_进程和线程2

    在之前的札记Python札记50_进程和线程1中介绍了进程、线程和子进程以及多进程的相关知识,本札记中重点介绍多线...

  • 5. python多进程锁-实现简易抢票

    一、主题 Lock类与RLock类相同:由于进程之间随机调度:某进程可能执行n条后,CPU接着执行其他进程。为了多...

网友评论

      本文标题:多进程

      本文链接:https://www.haomeiwen.com/subject/skoxuqtx.html