前言
提示:以下是本篇文章正文内容,下面案例可供参考
一、进程锁
进程之间,运行程序的时候多进程中,进程之间应避免进行通信,如果要进行通信就要用比较安全的工具,比如进程锁来解决此类问题(实现数据共享),实际中,可能大多使用数据库来解决进程和进程之间处理数据共享的问题。
进程之间的数据是相对独立的
实例
import time,os,random
from multiprocessing import Process,Manager,Lock
def work(d,lock):
with lock:
d['count'] -=1
def main():
lock = Lock()#进程锁
with Manager() as m:
dic = m.dict({'count':100})
p_list = []
for i in range(98):
p = Process(target=work,args=(dic,lock,))
p_list.append(p)
p.start()
for p in p_list:
p.join()
print(dic)
pass
if __name__=='__main__':
main()
运行结果为:
{'count': 2}
Process finished with exit code 0
在python程序运行时将某一个进程锁住。那么这个进程知道里面的任务执行完毕主动释放后才会解锁让下一个任务去使用这个进程,进程锁就像是保护进程任务的一个工具一样。
二、进程池
比如你有成千上万个任务要去执行,并不是直接创建成千上万的进程!!
创建进程、销毁进程——不能无限制的根据任务去开启进程做事。。。。
池子——固定数量的进程。
有事情了,从进程池里拿一个进程出来做事,做完事,不关闭进程!放回池子里继续等待下一个任务。
示例一(进程池)
import time,os,random
from multiprocessing import Pool
def func(n):
for i in range(10):#把1-100每个数字打印10次
print(n+1)
def main():
start = time.time()
pool = Pool(5) #池子里五个进程
pool.map(func,range(100))#定义一百个任务
t2 = (time.time()-start)
print(t2)
共消耗时间:
0.13670897483825684
示例二(多进程)
import time,os,random
from multiprocessing import Pool,Process
def func(n):
for i in range(10):#把1-100每个数字打印10次
print(n+1)
def main():
start = time.time()
'''
pool = Pool(5) #池子里五个进程
pool.map(func,range(100))#定义一百个任务
'''
p_list = []
for i in range(100):
p = Process(target=func,args=(i,))
p_list.append(p)
p.start()
for p in p_list:
p.join()
t2 = (time.time()-start)
print(t2)
pass
if __name__=='__main__':
main()
共消耗时间:
1.9545559883117676
进程池同步和异步的调用👇
同步调用:在发出一个任务时,自任务开始运行直到结束(可能遇到IO),只有返回一个返回值之后,才会发出下一个任务。
异步调用:一次发布多个任务,然后就直接执行下一行代码。不用等待结束。
shutdown:
1.让主进程等待进程池中所有的子进程都结束后,再执行。
2. 在上一个进程池没有完成所有的任务之前,不允许添加新任务。
一个任务是通过一个函数实现的,任务完成了,它的返回值就是函数的返回值。
实例(同步调用)——拿到结果为止。。。。
import time,os,random
from multiprocessing import Pool,Process
#同步调用
def work(n):
print("%s running"%(os.getpid()))
time.sleep(2)
return n**2
def main():
p = Pool(3)
res_l = []
for i in range(10):
res = p.apply(work,args=(i,))#同步调用,直到拿到结果为止,不管任务是否阻塞,同步调用都会在原地等着。
res_l.append(res)
print(res_l)
pass
if __name__=='__main__':
main()
运行结果为:
3964 running
11388 running
12504 running
3964 running
11388 running
12504 running
3964 running
11388 running
12504 running
3964 running
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Process finished with exit code 0
实例(异步调用)
import time,os,random
from multiprocessing import Pool,Process
#同步调用
def work(n):
print("%s running"%(os.getpid()))
time.sleep(2)
return n**2
def main():
p = Pool(3)
res_l = []
for i in range(10):
res = p.apply_async(work,args=(i,))#异步调用,三个进程不会同时开启同时结束
res_l.append(res)
p.close()
p.join()#异步提交任务,主进程需要join,等待进程池里的任务都处理完后,可以用get去搜集结果。
#如果不用join,主进程结束,进程池还没来的及执行,跟着结束
print(res_l)#但是打印出来的是对象
for r in res_l:
#需要使用get去获取apply_async的结果,因为apply没有get方法
print(r.get())
pass
if __name__=='__main__':
main()
运行结果为:
17832 running
17560 running
20460 running
17832 running
17560 running
20460 running
17832 running
20460 running
17560 running
17832 running
[<multiprocessing.pool.ApplyResult object at 0x0000018665A33FC8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A600C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60188>, <multiprocessing.pool.ApplyResult object at 0x0000018665A602C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60408>, <multiprocessing.pool.ApplyResult object at 0x0000018665A605C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60708>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60848>, <multiprocessing.pool.ApplyResult object at 0x0000018665A609C8>, <multiprocessing.pool.ApplyResult object at 0x0000018665A60588>]
0
1
4
9
16
25
36
49
64
81
Process finished with exit code 0
三、简易进程池聊天程序
首先要查看一下默认pool进程数是cpu的核心数量(os.cpu_count())
查看我本机的cpu核心数量👇
import time,os,random
from multiprocessing import Pool,Process
def main():
a = os.cpu_count()
print(a)
pass
if __name__=='__main__':
main()
运行结果为:
8
server.py服务端程序如下:
#! /usr/bin/python
# -*- coding:UTF-8 -*-
from socket import *
import os
from multiprocessing import Pool
#服务端程序
server = socket(AF_INET,SOCK_STREAM)
#当socket被关闭之后,立刻重新使用端口,配合使用异步通信
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind(('127.0.0.1',8080))
server.listen(5)
def talk(conn,addr):
print("进程%s 用户%s"%(os.getpid(),addr))
while True:
try:
msg = conn.recv(1024)
if not msg:break
conn.send(msg.upper())
except Exception:
break
def main():
p = Pool(4)#进程池里只开四个进程
while True:
conn,addr = server.accept()
p.apply_async(talk,args=(conn,addr,))
pass
if __name__ == '__main__':
main()
client.py客户端程序如下:
#! /usr/bin/python
# -*- coding:UTF-8 -*-
from socket import *
#客户端程序
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
def main():
while True:
msg = input(">> ").strip()
if not msg:continue
client.send(msg.encode("utf-8"))
msg = client.recv(1024)
print(msg.decode("utf-8"))
pass
if __name__ == '__main__':
main()
分别运行起来后:
多开几个cmd运行也是可以的
ps:这个程序实现的最多就是四个client......第五个以后的需要排队等待前面四个有一个退出才能连上通信