回顾一下线程和进程
线程与进程的区别
守护线程:
队列:
两种方式:
先进先出 #
后入先出 #卖水果,后来的来的是新的
生产者消费者模型:
生产包子,
吃包子
事件 event:
红绿灯模型
什么时候需要多线程:
多进程:
可以起8个进程,每个进程起一个线程,就可以利用多核运算,缺点就是进程之间不能共享数据。
例子:
每一个子进程都有一个父进程启动:
from multiprocessing import Process import os def info(title): print(title) print('module name:', __name__) print('parent process:', os.getppid()) print('process id:', os.getpid()) print(" ") def f(name): info(' 33[31;1mcalled from child process function f 33[0m') print('hello', name) if __name__ == '__main__': info(' 33[32;1mmain process line 33[0m') p = Process(target=f, args=('bob',)) p.start()
消息队列:
线程之间通讯:
进程间通信:
实践进程q
from multiprocessing import Process,Queue def f(qq): qq.put(['yang',12,'hehe']) if __name__ == '__main__': q = Queue() p = Process(target=f,args=(q,)) p.start() print(q.get())
线程q:
管道:
感觉和消息队列差不多
实践:
from multiprocessing import Process, Pipe def f(conn): conn.send([42, None, 'hello from child']) conn.send([42, None, 'hello from child2']) print("from parent:",conn.recv()) conn.close() if __name__ == '__main__': parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) # prints "[42, None, 'hello']" print(parent_conn.recv()) # prints "[42, None, 'hello']" parent_conn.send("张洋可好") # prints "[42, None, 'hello']" p.join()
进程之间数据的真正共享:
实践,进程间共享数据:
from multiprocessing import Process,Manager import os def f(dic,list): dic[os.getpid()] = os.getpid() list.append(os.getpid()) print(list) if __name__ == '__main__': with Manager() as manager: d = manager.dict() l = manager.list(range(5)) p_list = [] for i in range(10): p = Process(target=f,args=(d,l)) p.start() p_list.append(p) for res in p_list: res.join() print(d) print(l)
multiprocess
Queue Pipe 只是实现进程间数据的传递
Manager 实现了进程间数据的共享,即多个进程可以修改同一份数据
这里有个坑:
windows 多进程 必须加
不然会报错
作用:
if __name__ == '__main__':
会检查是否是主动运行,又或者是其他程序调用
如果调用,就不会执行 if __name__ == '__main__': 后面的代码
如果是手动执行,就会正常执行
进程池:
进城池有两种方法:
apply 串行
applu_async 并行