可重复利用的线程
from threading import Thread
from queue import Queue
import time
def func1():
time.sleep(1)
print('任务一完成')
def func2(*args,**kwargs):
time.sleep(2)
print('任务二完成',args,kwargs)
class MyThread(Thread):
def __init__(self,queue):
super().__init__()
self.queue = queue
self.daemon = True # 守护线程
def run(self):
while True:
func,args,kwargs = self.queue.get() # 从队列中拿到函数名
func(*args,**kwargs) # 调用函数
self.queue.task_done() # 计数器减一
def apply_async(self,func,*args,**kwargs):
# 往队列中添加任务(把参数也丢进去) 注意:是元组(不可变)
self.queue.put( (func,args,kwargs) )
def join(self):
# 如果队列计数器不为0 等待为0(等队列元素全被put)
self.queue.join() # 阻塞 直到队列中没有数据
queue = Queue()
my_thread = MyThread(queue)
# task_list = [func1,func2]
#
# for func in task_list:
# my_thread.apply_async(func,)
my_thread.apply_async(func1)
my_thread.apply_async(func2,1,2,a=1,b=2)
my_thread.start() # 调用run()
my_thread.join() # 调用自定义的join()
ssh://pyvip@127.0.0.1:1234。。。
任务一完成
任务二完成 (1, 2) {'b': 2, 'a': 1}
Process finished with exit code 0
线程池的简单实现
主线程: 相当于生产者,
只管向线程池提交任务,并不关心线程池是如何执行任务的。
因此,并不关心是哪一个线程执行的这个任务。
线程池: 相当于消费者,负责接收任务,
并将任务分配到一个空闲的线程中去执行。
from threading import Thread
from queue import Queue
import time
def func1():
time.sleep(1)
print('任务一完成')
def func2(*args, **kwargs):
time.sleep(2)
print('任务二完成', args, kwargs)
class MyThreadPool():
def __init__(self, n):
self.queue = Queue()
for i in range(n): # 守护线程
Thread(target=self.worker, daemon=True).start() # 注意start
def worker(self):
while True:
func,args,kwargs = self.queue.get() # 从队列中拿到函数名
func(*args, **kwargs) # 调用函数
self.queue.task_done() # 计数器减一
def apply_async(self, func, *args, **kwargs):
self.queue.put( (func,args,kwargs) ) # 往队列中添加任务
def join(self):
self.queue.join() # 阻塞 直到队列中没有数据
pool = MyThreadPool(4) # 线程池里有4个线程准备
pool.apply_async(func1) # 提交任务
pool.apply_async(func2, 1, 2, c=3, d=4)
pool.join()
ssh://pyvip@127.0.0.1:1234/。。。。
任务一完成
任务二完成 (1, 2) {'d': 4, 'c': 3}
Process finished with exit code 0
Python自带池
内置线程池
from multiprocessing.pool import ThreadPool
import time
def func1():
time.sleep(1)
print('任务一完成')
def func2(*args, **kwargs):
time.sleep(2)
print('任务二完成', args, kwargs)
pool = ThreadPool(4) # 线程池里有4个线程准备
pool.apply_async(func1) # 提交任务
pool.apply_async(func2, args=(1, 2), kwds={'a': 1, 'b': 2})
pool.close() # 关闭线程池 不允许再提交任务
pool.join() # 阻塞 等待线程池里的任务执行完成 再继续运行
任务一完成
任务二完成 (1, 2) {'b': 2, 'a': 1}
内置的进程池
from multiprocessing import Pool
import time
def func1():
time.sleep(1)
print('任务一完成')
def func2(*args, **kwargs):
time.sleep(2)
print('任务二完成', args, kwargs)
pool = Pool(4)
pool.apply_async(func1)
pool.apply_async(func2, args=(1, 2), kwds={'a': 1, 'b': 2})
pool.close()
pool.join()
任务一完成
任务二完成 (1, 2) {'b': 2, 'a': 1}
池的操作
操作一: close - 关闭提交通道,不允许再提交任务
操作二: apply_async – 向池中提交任务
操作三: terminate - 中止进程池,中止所有任务
from multiprocessing import Pool
import time
def func():
time.sleep(2)
print('hhAH')
pool = Pool(2)
pool.apply_async(func)
pool.close()
pool.join()
ssh://pyvip@127.0.0.1:1234。。。
hhAH
Process finished with exit code
from multiprocessing import Pool
import time
def func():
time.sleep(2)
print('hhAH')
pool = Pool(2)
pool.apply_async(func)
pool.close()
pool.terminate()
pool.join()
ssh://pyvip@127.0.0.1:1234。。。
Process finished with exit code 0
使用池来实现并发服务器
使用线程池来实现并发服务器
import socket
from multiprocessing.pool import ThreadPool
server = socket.socket()
server.bind(('0.0.0.0',8889))
server.listen(100)
# 消费者
def worker(conn):
while True:
try:
data = conn.recv(1024)
if data:
print(data.decode())
conn.send(data)
else:
conn.close()
break
except Exception as e:
print(e)
conn.close()
break
# 生产者
pool = ThreadPool(4)
while True:
conn, addr = server.accept()
pool.apply_async(worker, args=(conn,))
# 不需要join 消费者是while TRUE 不会结束。
import socket
client = socket.socket()
client.connect(('127.0.0.1',8880))
while True:
data = input('请输入:')
if data:
client.send(data.encode())
print(client.recv(1024).decode())
else:
break
client.close()
使用进程池来实现并发服务器
import socket
from multiprocessing import Pool
server = socket.socket()
server.bind(('0.0.0.0',8888))
server.listen(100)
# 消费者
def worker(conn):
while True:
try:
data = conn.recv(1024) # 拿池里的conn
if data:
print(data.decode())
conn.send(data)
else:
conn.close()
break
except Exception as e:
print(e)
conn.close()
break
# 生产者
# 池里只能有4个线程 并发量4 同时可以有4个客户端来连接(除非有客户端关闭连接)
pool = Pool(4)
while True:
conn, addr = server.accept() # 生成对等连接套接字
pool.apply_async(worker, args=(conn,)) # 把对等连接套接字conn丢进线程池里 池满了会阻塞
# 不需要join 消费者是while TRUE 不会结束。
import socket
client = socket.socket()
client.connect(('127.0.0.1',8888))
while True:
data = input('请输入:')
if data:
client.send(data.encode())
print(client.recv(1024).decode())
else:
break
client.close()
使用进程池+线程池来实现并发服务器
import socket
from multiprocessing import Pool, cpu_count # 进程池
from multiprocessing.pool import ThreadPool # 线程池
server = socket.socket()
server.bind(('0.0.0.0',8888))
server.listen(5)
# 消费者
def worker(conn):
while True:
try:
data = conn.recv(1024)
if data:
print('收到:',data.decode())
conn.send(data)
else:
conn.close()
break
except Exception as e:
print(e)
conn.close()
break
# 生产者
def worker_process(server):
# 每一个进程监听客户端连接 不停地生成对等连接套接字 处理消息
pool = ThreadPool(cpu_count() * 2) # 创建线程池 开cpu*2个线程
# 一个进程不停的等待客户端建立连接
while True:
# 多个进程accept等人连接 有人连接就把对等连接套接字丢进线程池里
# 每一个进程监听客户端连接 不停地生成对等连接套接字 处理消息
conn, addr = server.accept() # 生成对等连接套接字
pool.apply_async(worker, args=(conn,)) # 把对等连接套接字丢进线程池
# 2个进程 2个生产者 生成监听套接字 丢进进程池里 生成等连接套接字 丢进线程池里
n = cpu_count() # 打印当前电脑cpu个数n 2
process_pool = Pool(n) # 创建进程池 开n个进程 进程处理连接
for i in range(n):
# 把监听套接字 任务(建立连接 处理消息) 丢进进程池
process_pool.apply_async(worker_process, args=(server,))
process_pool.close() # 关闭池
process_pool.join() # 等待池里面的任务执行完
开2个进程 每个进程开4个线程 故可以同时连接8个客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1',8888))
while True:
data = input('请输入:')
if data:
client.send(data.encode())
print(client.recv(1024).decode())
else:
break
client.close()
没注释的
from multiprocessing.pool import ThreadPool
from multiprocessing import Pool,cpu_count
import socket
server = socket.socket()
server.bind(('0.0.0.0',8889))
server.listen(5)
def worker(conn):
while True:
try:
data = conn.recv(1024)
if data:
print('data: ',data.decode())
conn.send(data)
else:
conn.close()
break
except Exception as e:
print(e)
conn.close()
break
def worker_process(server):
thread_pool = ThreadPool(cpu_count() * 2)
while True:
conn, addr = server.accept()
thread_pool.apply_async(worker, args=(conn,))
n = cpu_count()
process_pool = Pool(n)
for i in range(n):
process_pool.apply_async(worker_process,args=(server,))
process_pool.close()
process_pool.join()
作业:实现一个基于多进程与多进程的并发服务器。
即 使用进程池+线程池来实现并发服务器