回顾一下线程和进程
线程与进程的区别
守护线程:
队列:
两种方式:
先进先出 #
后入先出 #卖水果,后来的来的是新的
生产者消费者模型:
生产包子,
吃包子
事件 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("\n\n")
def f(name):
info('\033[31;1mcalled from child process function f\033[0m')
print('hello', name)
if __name__ == '__main__':
info('\033[32;1mmain process line\033[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 并行