Python全栈最全学习之路-网络编程(六)

进程池与线程池

一、可重复利用的线程

1、队列计数器

如何保证队列为空了呢?

import queue
q = queue.Queue(3)
q.join() # 这个时候是不会阻塞的
q.put('a') # put之后就会阻塞,因为队列内部有个计数器,每次put都会加1
q.get() # get时计数器并不会减一
q.task_done() # 调用这个方法才会

队列计数器
队列自己内部有一个计数器,当计数为0时,join不会阻塞,否则就会阻塞

2、可重复利用线程

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()

Python全栈最全学习之路-网络编程(六)_第1张图片
线程的重复利用
利用生产者与消费者模型,实现线程的重复利用,主进程可以看成生产者,主要产生任务线程作为消费者主要处理任务

二、线程池

1、线程池的概念

Python全栈最全学习之路-网络编程(六)_第2张图片

主线程:类似于生产者,用来生成任务
线程池:类似消费者,用来处理任务

2、线程池的实现

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()

Python全栈最全学习之路-网络编程(六)_第3张图片
线程池
通过线程池来实现,多线程同时解决问题

三、内置池

1、内置线程池

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已经内置了线程池,提供了更多验证,更加安全

2、内置进程池

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()

Python全栈最全学习之路-网络编程(六)_第4张图片

四、并发服务器

1、线程池实现并发服务器

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,)) # 将发送消息利用线程池去处理

2、进程池与线程池实现

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()

你可能感兴趣的:(python全栈学习,python,多线程,网络,队列)