进程池、线程池 提交任务的两种方式: 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的 异步调用:提交完一个任务之后,不在原地等待,结果???,而是直接执行下一行代码,会导致任务是并发执行的 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的,,结果futrue对象会在任务运行完毕后自动传给回调函数 多线程实现套接字服务端支持并发 客户端.py from socket import *
client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8081))
while True: msg=input('>>: ').strip() if len(msg) == 0:continue client.send(msg.encode('utf-8')) data=client.recv(1024) print(data.decode('utf-8'))
服务端.py from socket import * from threading import Thread
def comunicate(conn): while True: # 通信循环 try: data = conn.recv(1024) if len(data) == 0: break conn.send(data.upper()) except ConnectionResetError: break conn.close()
def server(ip, port, backlog=5): server = socket(AF_INET, SOCK_STREAM) server.bind((ip, port)) server.listen(backlog)
while True: # 链接循环 conn, client_addr = server.accept() print(client_addr)
# 通信 t=Thread(target=comunicate,args=(conn,)) t.start()
if __name__ == '__main__': s=Thread(target=server,args=('127.0.0.1',8081)) s.start() 结果可以开启多个客户端,输入也有回复
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time,random,os
def task(name,n): print('%s%s is running' %(name,os.getpid())) time.sleep(random.randint(1,3)) return n**2
if __name__ == '__main__': # print(os.cpu_count()) p=ProcessPoolExecutor(4) l=[] for i in range(5): # 同步提交 # res=p.submit(task,'进程pid: ',i).result() # print(res)
# 异步提交 future=p.submit(task,'进程pid: ',i) l.append(future)
p.shutdown(wait=True) #关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕
for future in l: print(future.result()) print('主')
结果: 进程pid: 5888 is running 进程pid: 2744 is running 进程pid: 3516 is running 进程pid: 6320 is running 进程pid: 6320 is running 1 4 9 16 25 主
同步提交: 结果: 进程pid: 5080 is running 0 进程pid: 3060 is running 1 进程pid: 6636 is running 4 进程pid: 3372 is running 9 进程pid: 5080 is running 16 进程pid: 3060 is running 25 进程pid: 6636 is running 36 进程pid: 3372 is running 49 进程pid: 5080 is running 64 进程pid: 3060 is running 81 主
单线程下实现并发的套接字 客户端.py from threading import Thread,current_thread from socket import *
def client(): client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8080))
n=0 while True: msg='%s say hello %s' %(current_thread().name,n) n+=1 client.send(msg.encode('utf-8')) data=client.recv(1024) print(data.decode('utf-8'))
if __name__ == '__main__': for i in range(500): t=Thread(target=client) t.start()
服务端.py from gevent import monkey;monkey.patch_all() from socket import * from gevent import spawn
def comunicate(conn): while True: # 通信循环 try: data = conn.recv(1024) if len(data) == 0: break conn.send(data.upper()) except ConnectionResetError: break conn.close()
def server(ip, port, backlog=5): server = socket(AF_INET, SOCK_STREAM) server.bind((ip, port)) server.listen(backlog)
while True: # 链接循环 conn, client_addr = server.accept() print(client_addr)
# 通信 spawn(comunicate,conn)
if __name__ == '__main__': g1=spawn(server,'127.0.0.1',8080) g1.join() 协程 1. 目标: 在线程下实现并发 并发(多个任务看起来是同时执行就是并发):切换+保存状态
2. 协程: 协程是单线程实现并发 注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)
在单线程下实现多个任务间遇到IO就切换就可以降低单线程的IO时间,从而最大限度地提升单线程的效率 串行执行 import time
def func1(): for i in range(10000000): i+1
def func2(): for i in range(10000000): i+1
start = time.time() func1() func2() stop = time.time() print(stop - start) 结果: 4.8352766036987305
基于yield并发执行 import time def func1(): while True: print('func1') 10000000+1 yield
def func2(): g=func1() for i in range(10000000): print('func2') time.sleep(5) i+1 next(g)
start=time.time() func2() stop=time.time() print(stop-start) 结果: func2 func1 func2 func1 后面无限循环
from gevent import monkey;monkey.patch_all() from gevent import spawn,joinall #pip3 install gevent import time
def play(name): print('%s play 1' %name) time.sleep(5) print('%s play 2' %name)
def eat(name): print('%s eat 1' %name) time.sleep(3) print('%s eat 2' %name)
start=time.time() g1=spawn(play,'刘清正') g2=spawn(eat,'刘清正')
g1.join() g2.join() # joinall([g1,g2]) print('主',time.time()-start)
结果: 一个进程五百个线程