多进程多线程练习

多进程multiprocessing

1
#coding:utf-8
import time
import random
import os
from multiprocessing import Process

def down(text):
    print(f'{text}开始下载.....子进程id:{os.getpid()}')
    down_time = random.randint(2,5)
    time.sleep(down_time)
    print(f'{text}下载成功,耗时{down_time}秒......')

def main():
    print(f'这里是主进程,{os.getpid()}')
    start_time = time.time()
    t1 = Process(target=down,args=('中国历史', ))
    t2 = Process(target=down,args=('世界历史', ))
    t1.start()
    t2.start()
    end_time = time.time()
    print(f'任务下载完成,共耗时{end_time - start_time}秒')

if __name__ == '__main__':
    main()

2

#coding:utf-8
import time
import random
import os
from multiprocessing import Process

def down(text):
    print(f'{text}开始下载.....子进程id:{os.getpid()}')
    down_time = random.randint(2,5)
    time.sleep(down_time)
    print(f'{text}下载成功,耗时{down_time}秒......')

def main():
    print(f'这里是主进程,{os.getpid()}')
    start_time = time.time()
    t1 = Process(target=down,args=('中国历史', ))
    t2 = Process(target=down,args=('世界历史', ))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    end_time = time.time()
    print(f'任务下载完成,共耗时{end_time - start_time}秒')

if __name__ == '__main__':
    main()

3

#coding:utf-8
import time
import random
import os
from multiprocessing import Process

def down(text):
    print(f'{text}开始下载.....子进程id:{os.getpid()}')
    down_time = random.randint(2,5)
    time.sleep(down_time)
    print(f'{text}下载成功,耗时{down_time}秒......')

def main():
    print(f'这里是主进程,{os.getpid()}')
    start_time = time.time()
    t1 = Process(target=down,args=('中国历史', ))
    t2 = Process(target=down,args=('世界历史', ))
    t1.daemon = True
    t2.daemon
    t1.start()
    t2.start()
    end_time = time.time()
    print(f'任务下载完成,共耗时{end_time - start_time}秒')

if __name__ == '__main__':
    main()

4

import os
import threading
import multiprocessing

print('Main:',os.getpid())

def worker(sign,lock):
    lock.acquire()
    print(sign,os.getpid())
    lock.release()

record = []
lock = threading.Lock()

record = []
lock = multiprocessing.Lock()
if __name__ == '__main__':
    for i in range(5):
        thread = threading.Thread(target=worker,args=('thread',lock))
        thread.start()
        record.append(thread)
    for thread in record:
        thread.join()
    for i in range(5):
        process = multiprocessing.Process(target=worker,args=('process',lock))
        process.start()
        record.append(process)
    for process in record:
        process.join()

5

正如我们在Linux多线程中介绍的管道PIPE和消息队列message queue,multiprocessing包中有Pipe类和Queue类来分别支持这两种IPC机制。Pipe和Queue可以用来传送常见的对象。

Pipe可以是单向(half-duplex),也可以是双向(duplex)。我们通过mutiprocessing.Pipe(duplex=False)创建单向管道 (默认为双向)。一个进程从PIPE一端输入对象,然后被PIPE另一端的进程接收,单向管道只允许管道一端的进程输入,而双向管道则允许从两端输入。
 

import multiprocessing as mul

def proc1(pipe):
    pipe.send('hello')
    print('proc1 rec:',pipe.recv())

def proc2(pipe):
    print('proc2 rec:',pipe.recv())
    pipe.send('hello,too')

pipe = mul.Pipe()
if __name__ == '__main__':
    p1 = mul.Process(target=proc1,args=(pipe[0],))
    p2 = mul.Process(target=proc2,args=(pipe[1],))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

6

这里的Pipe是双向的。

Pipe对象建立的时候,返回一个含有两个元素的表,每个元素代表Pipe的一端(Connection对象)。我们对Pipe的某一端调用send()方法来传送对象,在另一端使用recv()来接收。

Queue与Pipe相类似,都是先进先出的结构。但Queue允许多个进程放入,多个进程从队列取出对象。Queue使用mutiprocessing.Queue(maxsize)创建,maxsize表示队列中可以存放对象的最大数量。
 

import os
import multiprocessing
import time

def inputQ(queue):
    info = str(os.getpid()) + '(put):' + str(time.time())
    queue.put(info)

def outputQ(queue,lock):
    info = queue.get()
    lock.acquire()
    print(str(os.getpid()) + ' get: ' + info)
    lock.release()

record1 = []
record2 = []
lock = multiprocessing.Lock()
queue = multiprocessing.Queue(3)

if __name__ == '__main__':
    for i in range(10):
        process = multiprocessing.Process(target=inputQ,args=(queue,))
        process.start()
        record1.append(process)
    for i in range(10):
        process = multiprocessing.Process(target=outputQ,args=(queue,lock))
        process.start()
        record2.append(process)
    for p in record1:
        p.join()
    queue.close()

    for p in record2:
        p.join()
7

进程池 (Process Pool)可以创建多个进程。这些进程就像是随时待命的士兵,准备执行任务(程序)。一个进程池中可以容纳多个待命的进程。

import multiprocessing as mul

def f(x):
    return x **  2
if __name__ == '__main__':
    pool = mul.Pool(5)
    rel = pool.map(f,[1,2,3,4,5,6,7,8,9,10])
    print(rel)

我们创建了一个容许5个进程的进程池 (Process Pool) 。Pool运行的每个进程都执行f()函数。我们利用map()方法,将f()函数作用到表的每个元素上。这与built-in的map()函数类似,只是这里用5个进程并行处理。如果进程运行结束后,还有需要处理的元素,那么的进程会被用于重新运行f()函数。除了map()方法外,Pool还有下面的常用方法。

apply_async(func,args) 从进程池中取出一个进程执行func,args为func的参数。它将返回一个AsyncResult的对象,你可以对该对象调用get()方法以获得结果。

close() 进程池不再创建新的进程

join() wait进程池中的全部进程。必须对Pool先调用close()方法才能join。

8

import multiprocessing
def func1(a,arr):
    a.value = 3.14
    for i in range(len(arr)):
        arr[i] = 0
    a.value = 0

if __name__ == '__main__':
    num = multiprocessing.Value('d',1.0)
    arr = multiprocessing.Array('i',range(10))
    p = multiprocessing.Process(target=func1,args=(num,arr))
    p.start()
    p.join()
    print(num.value)
    print(arr[:])

这里我们实际上只有主进程和Process对象代表的进程。我们在主进程的内存空间中创建共享的内存,也就是Value和Array两个对象。对象Value被设置成为双精度数(d), 并初始化为1.0。而Array则类似于C中的数组,有固定的类型(i, 也就是整数)。在Process进程中,我们修改了Value和Array对象。回到主程序,打印出结果,主程序也看到了两个对象的改变,说明资源确实在两个进程之间共享。
 

9

import time
import random
from multiprocessing import Process

class DownTask(Process):
    def __init__(self,text):
        super().__init__()
        self.text = text
    def run(self):
        print(f'{self.text}开始下载...')
        down_time = random.randint(2,5)
        time.sleep(down_time)
        print(f'{self.text}下载成功,耗时{down_time}秒....')

def main():
    start = time.time()
    t1 = DownTask('中国历史')
    t1.start()
    t2 = DownTask('世界历史')
    t2.start()
    # t1.join()
    # t2.join()
    end = time.time()
    print('总共耗费了%.2f秒.' % (end - start))

if __name__ == '__main__':
    main()

10

使用进程池Pool创建进程

Pool进程池,可以把进程池比做一个水池,假设我们要完成放满10个水盆水的任务,在这个水池中,最多可以放三个水盆,也就是最多能用三个水盆接水。

Pool有2种启动方式,

1. apply_async()  非阻塞方式(并行,异步),见下,下面代码创建了一个3个进程的进程池,在执行10个任务时,每次都是同时三个进程启动执行三个任务。回到放水任务,相当于有三个水笼头,三个水盆同时接水,每个水盆接满了就将水倒进桶里再重新接水。一直接满10个水盆的水。这三个水盆是同时接水的,并行,异步,互不干涉。

import os
import time
from multiprocessing import Pool

def task(name):
    print(f'子进程{os.getpid()},执行task:{name}')
    time.sleep(5)

def main():
    print(f'父进程{os.getpid()}.')
    p = Pool(3)
    for i in range(10):
        p.apply_async(task,args=(i,))
    print('等待所有子进程结束')
    p.close()
    p.join()
    print('所有子进程结束')
if __name__ == '__main__':
    main()

11

apply(),阻塞式,进程池里的进程按顺序执行,必须一个进程执行完了才能继续下一个进程。回到放水任务,相当于有三个水盆,但是只有一个水笼头能用,三个水盆按顺序排好,一个接满了才能放另一个进去,轮流接水,一般不用这个方法来启动,失去了多进程的作用。

import os
import time
from multiprocessing import Pool

def task(name):
    print(f'子进程{os.getpid()},执行task:{name}')
    time.sleep(5)

def main():
    print(f'父进程{os.getpid()}.')
    p = Pool(3)
    for i in range(10):
        p.apply(task,args=(i,))
    print('等待所有子进程结束')
    p.close()
    p.join()
    print('所有子进程结束')
if __name__ == '__main__':
    main()

close(), 关闭Pool, 不再接受新的任务。即整个池子不再使用,已运行的进程会继续运行完。

terminate(), 不管任务是否完成,彻底终止任务,相当直接杀死进程,不管是运行的还是没运行的,所有进程all die!

参考

(100条消息) python多进程multiprocessing使用,看这篇就够了(二)_Neil.chen的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值