• ​​可重复利用的线程​​
  • ​​线程池的简单实现​​
  • ​Python自带池​
  • ​​内置线程池​​
  • ​​内置的进程池​​
  • ​​池的操作​​
  • ​使用池来实现并发服务器​
  • ​​使用线程池来实现并发服务器​​
  • ​​使用进程池来实现并发服务器​​
  • ​​使用进程池+线程池来实现并发服务器​​
  • ​​作业:实现一个基于多进程与多进程的并发服务器。​​


可重复利用的线程

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

作业:实现一个基于多进程与多进程的并发服务器。

即 使用进程池+线程池来实现并发服务器