多任务--进程

开启进程

步骤

  • 创建函数
  • 创建进程对象,并在target指定函数名
  • 开启进程

示例代码

import multiprocessing
import time


def work1():
    for i in range(50):
        print('正在扫地---', i)
        time.sleep(1)


def work2():
    for i in range(50):
        print('正在搬砖---', i)
        time.sleep(1)


def main():
    """测试进程的基本使用"""
    # 创建进程对象
    p1 = multiprocessing.Process(target=work1)

    # 开启进程
    p1.start()

    # 创建进程对象
    p2 = multiprocessing.Process(target=work2)

    # 开启进程
    p2.start()


if __name__ == '__main__':
    main()

进程号操作

Linux查看正在运行的进程:

ps aux

image

Linux查看正在运行指定进程

image

杀死进程

kill 进程号

程序中查看进程号

os.getpid()

程序中出看父进程号

os.getppid()

进程的执行顺序

  • 子进程代码执行结束后会自动销毁
  • 当所有的子进程结束,主进程才会结束
  • 当主进程结束,所有的子进程会同时结束
  • ==进程的执行是无序的==

进程间传参

  • 在定义子进程对象时,可以指定args或者kwargs为子进程传参
  • args 是一个元组
  • kwargs 是一个字典

示例代码

import multiprocessing


def work1(text, who='扫地僧'):
    for i in range(200):
        print('正在----',text, '---', who ,'---',i)
        open('02-UDP聊天器-多任务版.py').read()

def main():
    """验证进程的执行顺序
    """
    # 创建进程
    p1 = multiprocessing.Process(target=work1, args=('扫地',), kwargs={'who':'乔峰'})
    # 开启进程
    p1.start()

    p2 = multiprocessing.Process(target=work1, args=('搬砖',))
    p2.start()


if __name__ == '__main__':
    main()

进程间通信

因为主进程开启子进程时,会把主进程当前所有资源复制一份,并且主进程从上往下顺序执行,而子进程从指定的函数开始执行,所以==进程之间是没发共享数据的==,如果需要进程间==共享数据则需要用到Queue==

Queue(消息队列),遵循先进先出,每次get()时候都会获取当前队列中第一个元素,并且该元素会从队列中移除

Queue基本使用

  • 创建一个Queue,q = multiprocessing.Queue()
  • 向队列写数据 q.put(“”)
  • 从队里读数据 q.get()

示例代码

import multiprocessing


def work1(q):
    """向消息队列写入数据"""
    for i in range(5000):
        q.put('数据%d' % i)

    print('数据放入结束')


def work2(q):
    """从队列取出数据"""
    while True:
        print('work2--取出', q.get())


def main():
    """测试进程间通信"""
    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=work1, args=(q,))
    p1.start()

    # p1.join()
    p2 = multiprocessing.Process(target=work2, args=(q,))
    p2.start()


if __name__ == '__main__':
    main()

Queue常见方法说明

初始化Queue()对象时(例如:q=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);

进程池

基本使用

  • multiprocessing.Pool(3)#定义一个进程池,最大进程数3
  • Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
  • po.close() #关闭进程池,关闭后po不再接收新的请求
  • po.join() #等待po中所有子进程执行完成,必须放在close语句之后

示例代码

import multiprocessing
import os
import time


def work1(i):
    print('这是第 %d 个任务,使用的进程为 %d' % (i, os.getpid()))
    time.sleep(1)


def main():
    """测试进程池的使用"""
    # 创建进程池
    pool = multiprocessing.Pool(3)

    # 向进程池里放入任务
    for i in range(10):
        pool.apply_async(work1, (i,))


    # 默认情况下,主进程不会等待进程池执行结束
    pool.close()  # join 之前必须调用 close
    pool.join()  # join 可以让主进程等待进程池执行结束

if __name__ == '__main__':
    main()

进程池通信

进程池使用Queue必须要用 q = Manager().Queue()  

进程线程区别

 进程:1>系统进行资源分配和调度的一个独立单元
       2>进程间不共享全局变量,需要进行进程间的通信
       3>进程在运行过程中为独立的内存单元
线程: 1>进程的一个实体,是CPU调度和分派的基本单位
       2>同时对一个全局变量进行修改,容易混乱(不一定执行完就换线程)
       3>线程依赖进程的存在,线程并发性高,占用资源比进程少
       4>多线程共享非全局变量不用加锁
       5>多线程到同一个函数里执行,函数里的变量各是各的

猜你喜欢

转载自blog.csdn.net/weixin_40420525/article/details/80884696
今日推荐