Python学习_23 Python多进程和多线程(二)
多进程复习
1、Process 类
用来描述一个进程对象。创建子进程的时候,只需要传入一个执行函数和函数的参数即可完成 Process 示例的创建。
创建一个process对象
p = process(
target
=workker_1,
args
=(
2
,))
target :函数名称
args:函数需要的参数,以tuple的形式传入
注意:单个元素的tuple的表现形式:(1,),有个,号
p代表一个多进程
p.is_alive() 判断进程是否存活
p.run() 启动进程
p.start() 启动进程,会自动调run()方法,推荐使用start
p.join(timeout) 等待子进程结束或者到超时时间直接下一步
p.terminate() 强制子进程退出
p.name 进程的名字
p.pip 进程的pid
2、Lock组件
使用方法acquire()设置为locked状态;
使用release()设置为unlocked状态。
with Lock: 获取锁,完了之后自动释放锁
3、共享内存
python的multiprocessing模块提供了Value 和 Array 模块,可以在不同的进程中共同使用
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018\5\23 0023 21:44
# @Author : xiexiaolong
# @File : test.py
from multiprocessing import Process, Value, Array
def f(n, a,m):
n.value = 3.1415927
m = 20
print(a[:])
for i in range(len(a)):
a[i] = -a[i]
print(m)
if __name__ == '__main__':
num = Value('d', 0.0)
arr = Array('i', range(10))
m = 10
p = Process(target=f, args=(num, arr, m))
p.start()
p.join()
print(num.value)
print(arr)
print(arr[:])
print(m)
结果:
D:\python\venv\Scripts\python.exe D:/python/0522/test.py
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
20
3.1415927
<SynchronizedArray wrapper for <multiprocessing.sharedctypes.c_long_Array_10 object at 0x000000000297FDC8>>
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
10
Process finished with exit code 0
分析:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]####打印的是a的初始值
20 #####m的初始值
3.1415927 ##n的初始值
<SynchronizedArray wrapper for <multiprocessing.sharedctypes.c_long_Array_10 object at 0x000000000297FDC8>>
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9] ####当经过内存共享,子函数重写了a之后,发现主函数输出a的值也变了
10 ####经过内存共享,子函数重新定义了m之后,主函数打印m的值也变了
第二十三节课
4、服务进程Manager
上面的共享内存支持两种结构 Value 和 Array, 这些值在主进程中管理,很分散。 Python 中还有一统天下,无所不能的 Server process,专门用来做数据共享。 其支持的类型非常多,比如list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Queue, Value 和 Array 用法如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018\5\23 0023 21:44
# @Author : xiexiaolong
# @File : test.py
from multiprocessing import Process, Manager
def worker(dt, lt):
for i in range(10):
dt[i] = i*i
lt +=[x for x in range(11, 16)]
if __name__ == '__main__':
manager = Manager()
dt = manager.dict()
lt = manager.list()
p = Process(target=worker, args=(dt, lt))
p.start()
p.join(timeout=3)
print(dt)
print(lt)
结果;
D:\python\venv\Scripts\python.exe D:/python/0522/test.py
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
[11, 12, 13, 14, 15]
Process finished with exit code 0
5、进程池
Pool 是进程池,进程池能够管理一定的进程,当有空闲进程时,则利用空闲进程完成任务,直到所有任务完成为止;
Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018\5\23 0023 21:44
# @Author : xiexiaolong
# @File : test.py
import time
import multiprocessing
def fun(msg):
print("#########start#### {0}".format(msg))
time.sleep(3)
print("#########end###### {0}".format(msg))
if __name__ == '__main__':
print("start main")
pool = multiprocessing.Pool(processes=3)
for i in range(1, 7):
msg = "hello {0}".format(i)
pool.apply_async(fun, (msg,))
# pool.apply(fun, (msg,))
pool.close(
pool.join()
print("end main")
结果
D:\python\venv\Scripts\python.exe D:/python/0522/test.py
start main
#########start#### hello 1
#########start#### hello 2
#########start#### hello 3
#########end###### hello 1
#########start#### hello 4
#########end###### hello 2
#########start#### hello 5
#########end###### hello 3
#########start#### hello 6
#########end###### hello 4
#########end###### hello 5
#########end###### hello 6
end main
Process finished with exit code 0
分析:
pool.apply_async(fun, (msg,))# 执行时间6s+
pool.apply(fun, (msg,)) 6*3=18+#执行时间
pool.apply_async 非阻塞,定义的进程池最大数的同时执行
pool.apply 一个进程结束,释放回进程池,开始下一个进程
pool.close()#在调用join之前,要先调用close,否则会报错,close执行完不会有新的进程加入到pool
pool.join()#join 是等待所有的子进程结束
6、多线程
线程是应用程序中工作的最小单元,Python提供了threading模块来对多线程的操作,多线程有两种方式:
方法一:
将要执行的方法作为参数传给Thread的构造方法(和多进程类似)
t = threading.Thread(target=action, args=(i,))
方法二:
从Thread继承,并重写run()
例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018\5\23 0023 21:44
# @Author : xiexiaolong
# @File : test.py
import threading
def worker(args):
print("开始子进程 {0}".format(args))
print("结束子进程 {0}".format(args))
if __name__ == '__main__':
print("start main")
t1 = threading.Thread(target=worker, args=(1,))
t2 = threading.Thread(target=worker, args=(2,))
t1.start()
t2.start()
print("end main")
结果:
D:\python\venv\Scripts\python.exe D:/python/0522/test.py
start main
开始子进程 1
结束子进程 1
开始子进程 2
end main
结束子进程 2
Process finished with exit code 0
7、线程锁
通过threading.Lock()来创建锁,函数执行先要获得锁,然后执行,完成之后要释放锁
import threading
lock = threading.Lock()
##with lock:
lock.acquire()#获取锁
lock.release()#释放锁
8、线程池
通过传入一个参数组来实现多线程,并且它的多线程是有序的,顺序与参数组中的参数顺序保持一直
先要安装线程池的包pip install threadpool
通用格式:
from threadpool import *
pool = ThreadPool(size)
requests = makeRequests()
[pool.putRequest(req) for req in requests]
pool.wait()
实例:
方法一:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018\5\23 0023 21:44
# @Author : xiexiaolong
# @File : test.py
import threadpool
def hello(m, n, o):
print("m = {0} n={1} o={2}".format(m, n, o))
if __name__ == '__main__':
lst_vars_1 = ['1', '2', '3']
lst_vars_2 = ['4', '5', '6']
func_var = [(lst_vars_1, None), (lst_vars_2, None)]
pool = threadpool.ThreadPool(2)
requests = threadpool.makeRequests(hello, func_var)
[pool.putRequest(req) for req in requests]
pool.wait()
结果:
D:\python\venv\Scripts\python.exe D:/python/0522/test.py
m = 1 n=2 o=3
m = 4 n=5 o=6
Process finished with exit code 0
分析:
func_var = [(lst_vars_1,
None
), (lst_vars_2,
None
)] ##这里固定格式,必须后面写一个None
requests = threadpool.makeRequests(hello, func_var)
[pool.putRequest(req)
for
req
in
requests]
都是固定格式
方法二:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018\5\23 0023 21:44
# @Author : xiexiaolong
# @File : test.py
import threadpool
def hello(m, n, o):
print("m = {0} n={1} o={2}".format(m, n, o))
if __name__ == '__main__':
dict_vars_1 = {'m': '1', 'n': '2', 'o': '3'}
dict_vars_2 = {'m': '4', 'n': '5', 'o': '6'}
func_var = [(None, dict_vars_1), (None, dict_vars_2)]
pool = threadpool.ThreadPool(2)
requests = threadpool.makeRequests(hello, func_var)
[pool.putRequest(req) for req in requests]
pool.wait(
结果:
D:\python\venv\Scripts\python.exe D:/python/0522/test.py
m = 1 n=2 o=3
m = 4 n=5 o=6
Process finished with exit code 0
分析:
func_var = [(
None
, dict_vars_1), (
None
, dict_vars_2)] 这个也是固定格式