如何保证队列为空了呢?
import queue
q = queue.Queue(3)
q.join() # 这个时候是不会阻塞的
q.put('a') # put之后就会阻塞,因为队列内部有个计数器,每次put都会加1
q.get() # get时计数器并不会减一
q.task_done() # 调用这个方法才会
队列计数器
队列自己内部有一个计数器,当计数为0时,join不会阻塞,否则就会阻塞
import time
import queue
import threading
class MyThread(threading.Thread):
def __init__(self):
super().__init__()
self.daemon = True # 守护模式
self.queue = queue.Queue(3)
self.start() # 实例化的时候直接启动线程
def run(self):
while True: # 无限循环,不停执行任务
func,args,kwargs = self.queue.get() # 获取任务与参数
func(*args,**kwargs) # 执行任务
self.queue.task_done() # 让queue队列的计数减一
def submit_tasks(self,func,args=(),kwargs={}):
self.queue.put((func,args,kwargs)) # 提交任务
def join(self): # 等待所有任务执行完成
self.queue.join() # 查看队列技术是否执行完毕
def f1():
time.sleep(3)
print('任务1完成')
def f2(*args,**kwargs):
time.sleep(3)
print('任务2完成',args,kwargs)
t = MyThread()
t.submit_tasks(f1)
t.submit_tasks(f2,args=('a','b'),kwargs=({'a':1,'b':2}))
t.join()
线程的重复利用
利用生产者与消费者模型,实现线程的重复利用,主进程可以看成生产者,主要产生任务线程作为消费者主要处理任务
主线程:类似于生产者
,用来生成任务
线程池:类似消费者
,用来处理任务
import time
import queue
import threading
class MyPool:
def __init__(self,n):
self.queue = queue.Queue()
for i in range(n): # 初始化的时候,设置生成几个线程,也可以写成固定的
# 直接生成线程,并启动,线程始终启动的,并且设置成守护线程
threading.Thread(target=self.func,daemon=True).start()
# 这个线程的生命周期是其中之后,直到主进程结束
def func(self):
while True: # 不断获取要执行的任务
task,args,kwargs = self.queue.get() # 获取任务与参数
task(*args,**kwargs) # 执行任务
self.queue.task_done() # 队列的计数减一
def submit_tasks(self,func,*args,**kwargs):
self.queue.put((func,args,kwargs)) # 主进程不断添加任务
def join(self): # 等待所有任务执行完成
self.queue.join() # 查看队列技术是否执行完毕
def f1():
time.sleep(3)
print('任务1完成')
def f2(*args,**kwargs):
time.sleep(3)
print('任务2完成',args,kwargs)
t = MyPool(3)
t.submit_tasks(f1)
t.submit_tasks(f1)
t.submit_tasks(f2,args=('a','b'),kwargs=({'a':1,'b':2}))
t.submit_tasks(f1)
t.submit_tasks(f2,args=('a','b'),kwargs=({'a':1,'b':2}))
t.submit_tasks(f2,args=('a','b'),kwargs=({'a':1,'b':2}))
t.join()
import time
from multiprocessing.pool import ThreadPool
def f1():
time.sleep(3)
print('任务1完成')
def f2(*args,**kwargs):
time.sleep(3)
print('任务2完成',args,kwargs)
pool = ThreadPool(3)
pool.apply_async(f1) # apply_async 用来提交数据
pool.apply_async(f2,args=(1,2,3),kwds={'a':1,'b':2})
pool.apply_async(f1) # apply_async 用来提交数据
pool.apply_async(f2,args=(1,2,3),kwds={'a':1,'b':2})
pool.close() # 要求:在join前必须要close关闭提交
pool.join()
内置池
Python已经内置了线程池,提供了更多验证,更加安全
import time
from multiprocessing.pool import Pool
def f1():
time.sleep(3)
print('任务1完成')
def f2(*args,**kwargs):
time.sleep(3)
print('任务2完成',args,kwargs)
pool = Pool(2)
pool.apply_async(f1) # apply_async 用来提交数据
pool.apply_async(f2,args=(1,2,3),kwds={'a':1,'b':2})
result = pool.apply_async(f2,args=(1,2,3),kwds={'a':1,'b':2})
result.get() # 如果没有完成阻塞
pool.close() # 要求:在join前必须要close关闭提交
pool.join()
import socket
from multiprocessing import Pool,cpu_count
from multiprocessing.pool import ThreadPool
server = socket.socket()
server.bind(('127.0.0.1',8989))
server.listen(50)
def socket_recv(conn):
while True:
recv_data = conn.recv(1024)
if recv_data:
print(recv_data)
conn.send(recv_data)
else:
conn.close()
break
n = cpu_count() # 获取CPU的核心数
pool = ThreadPool(n) # 开启线程池,n为线程数
while True:
conn,addr = server.accept()
pool.apply_async(socket_recv,args=(conn,)) # 将发送消息利用线程池去处理
import socket
from multiprocessing import Pool,cpu_count
from multiprocessing.pool import ThreadPool
server = socket.socket()
server.bind(('0.0.0.0',8989))
server.listen(50)
def socket_recv(conn):
while True:
recv_data = conn.recv(1024)
if recv_data:
print(recv_data)
conn.send(recv_data)
else:
conn.close()
break
def accpet_process(server):
pool = ThreadPool(cpu_count() * 2 ) # 通常可以分配2倍的CPU个数
while True:
conn, addr = server.accept()
# 再次利用多线程来执行,糅合多线程和多进程
pool.apply_async(socket_recv, args=(conn,))
n = cpu_count() # 获取CPU的核心数
pool = Pool(n)
for i in range(n): # 为每一个cpu分配一个进程
pool.apply_async(accpet_process,args=(server,)) # 利用多进程来建立对等连接套接字
pool.apply_async(accpet_process,args=(server,)) # 利用多进程来建立对等连接套接字
pool.close()
pool.join()