因为GIL的存在,python中的多线程其实并非真正的多线程,若是想要充分地使用多核CPU的资源,在python中大部分状况须要使用多进程。
multiprocessing包是Python中的多进程管理包。与threading.Thread相似,它能够利用multiprocessing.Process对象来建立一个进程。该进程能够运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象能够像多线程那样,经过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。因此,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。python
#### process多线程
Process([group [, target [, name [, args [, kwargs]]]]])app
group:线程组,目前尚未实现,库引用中提示必须是None;异步
target:要执行的方法async
name:进程名函数
args/kwargs:要传入方法的参数线程
is_alive():返回进程是否在运行code
join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
start():进程准备就绪,等待CPU调度对象
run():strat()调用run方法,若是实例进程时未制定传入target,这star执行t默认run()方法。
继承
terminate():无论任务是否完成,当即中止工做进程
daemon:和线程的setDeamon功能同样守护进程
name:进程名字。
pid:进程号。
from multiprocessing import Process import time def foo(q): time.sleep(1) print(q) if __name__=="__main__": l=[] for i in range(3): p=Process(target=foo,args=("W")) l.append(p) p.start() for i in l: i.join() print("end") "D:\Program Files\python.exe" E:/py_code/进程队列/进程队列.py W W W end Process finished with exit code 0
上述进程的调用是比较常规的调用。
from multiprocessing import Process import time class MyProcess(Process): def __init__(self): super(MyProcess, self).__init__() # self.name = name def run(self): print ('hello', self.name,time.ctime()) time.sleep(1) if __name__ == '__main__': p_list=[] for i in range(3): p = MyProcess() p.start() p_list.append(p) for p in p_list: p.join() print('end') "D:\Program Files\python.exe" E:/py_code/进程队列/进程队列.py hello alvin:1 Thu Jul 20 18:07:56 2017 hello alvin:0 Thu Jul 20 18:07:56 2017 hello alvin:2 Thu Jul 20 18:07:56 2017 end Process finished with exit code 0
上面的代码定义了一个类并继承了一个进程,并开启了5个进程,这5个进程会均会执行MyProcess类中的run方法即打印 ('hello',self.name,time.ctime())。
from multiprocessing import Process,Queue import queue def foo(q): q.put("1") def bar(q): print(q.get(),"ok") if __name__=="__main__": q=Queue() #相等于q=queue.Queue() for i in range(3): p=Process(target=foo,args=(q,)) p1=Process(target=bar,args=(q,)) p1.start() p.start() "D:\Program Files\python.exe" E:/py_code/进程队列/进程队列.py 1 ok 1 ok 1 ok Process finished with exit code 0
管道()函数返回由管道链接的一对链接对象,该管道默认是双向的(双向的)。例如:
def foo(o): data=o.recv() print(data) o.send("hey!whatmini") if __name__=="__main__": sock,conn=Pipe()#sock与conn至关于管道的两个接口 # t1=Process(target=foo,args=(conn,)) t1.start() sock.send("你好") print(sock.recv()) "D:\Program Files\python.exe" E:/py_code/进程队列/进程队列.py 你好 hey!whatmini Process finished with exit code 0
须要注意的是:Pipe()返回的两个链接对象表明管道的两端。 每一个链接对象都有send()和recv()方法(等等)。 请注意,若是两个进程(或线程)尝试同时读取或写入管道的同一端,管道中的数据可能会损坏
Queue和pipe只是实现了数据交互,并没实现数据共享,即一个进程去更改另外一个进程的数据。
from multiprocessing import Process, Manager def foo(l,i): l.append(i*i) if __name__ == '__main__': with Manager() as manager: manager=Manager() l = manager.list([11,22,33]) #建立一个列表也能够字典类型都支持 p_list = [] for i in range(10): p = Process(target=foo, args=(l,i)) p.start() p_list.append(p) for res in p_list: res.join() print(l) "D:\Program Files\python.exe" E:/py_code/进程队列/进程队列.py [11, 22, 33, 4, 1, 9, 36, 81, 0, 49, 16, 64, 25] Process finished with exit code 0
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,若是进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
from multiprocessing import Pool # import time def foo(args): time.sleep(1) print(args) if __name__ == '__main__': p = Pool(5) #进程池对象的最大量为5个 for i in range(30): #30个任务5个进程对象去执行 p.apply_async(func=foo, args= (i,)) #异步执行 p.close() # 等子进程执行完毕后关闭线程池 # time.sleep(2) # p.terminate() # 马上关闭线程池 p.join() #主进程等待全部子进程执行完毕,必须在close或terminate以后
进程池内部维护一个进程序列,当使用时,去进程池中获取一个进程,若是进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有如下几个主要方法:
1 apply:从进程池里取一个进程并执行
2 apply_async:apply的异步版本
3 terminate:马上关闭线程池
4 join:主进程等待全部子进程执行完毕,必须在close或terminate以后
6 close:等待全部进程结束后,才关闭线程池