进程池与线程池、协程、协程实现TCP服务端并发、IO模型

一、进程池与线程池

1、线程池

'''
开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少
在计算机能够承受范围内最大限度的利用计算机
什么是池?
在保证计算机硬件安全的情况下最大限度的利用计算机
池其实是降低了程序的运行效率,但是保证了计算机硬件的安全
(硬件的发展跟不上软件的速度)
'''
from concurrent.futures import ThreadPoolExecutor
import time pool = ThreadPoolExecutor(5) # 括号中可以传参数,指定线程池内的线程个数,也可以不传,不传默认是当前所在计算机的CPU个数乘5 def task(n):
print(n)
time.sleep(2) # pool.submit(task, 1) # 朝线程池中提交任务,异步提交 '''
任务的提交方式:
同步:原地等待任务的返回结果
异步:不等待任务的返回结果,直接执行下一行代码
异步的结果怎么拿?
'''
for i in range(20):
res = pool.submit(task, i) # 任务(task)的返回结果,是Future类的一个对象
print(res) # <Future at 0x31aeeb0 state=pending>,这个对象是及时生成的,所以可以立马返回,不改变异步执行
# 但是res的值是在任务执行完以后才会有
# print(res.result()) # 通过result取值,并且是原地等待结果的返回,这一行代码直接将异步执行改为了同步执行
# 如果还是想要程序异步执行,同时还能拿到任务的返回结果,就要用一个列表将res全部放进去,待任务全部提交完以后,再for循环拿出res的值 # 异步提交任务,待任务全部执行完毕后,拿到任务的返回值
from concurrent.futures import ThreadPoolExecutor
import time def task(n):
print(n)
time.sleep(1)
return n ** 2 pool = ThreadPoolExecutor(5)
t_list = []
for i in range(20):
res = pool.submit(task, i)
t_list.append(res)
pool.shutdown() # 关闭池子,等待池子中所有的任务执行完毕后,才会往下运行代码
for t in t_list:
print('>>>>:', t.result())

2、进程池+异步回调机制

from concurrent.futures import ProcessPoolExecutor
import time
import os pool = ProcessPoolExecutor(5) def task(n):
print(n,os.getpid()) #获取当前进程号
time.sleep(1)
return n ** 2 def call_back(n):
print('拿到了异步提交任务的返回结果', n.result()) if __name__ == '__main__':
t_list = []
for i in range(20):
res = pool.submit(task, i).add_done_callback(call_back) # 提交任务的时候,绑定一个回调函数,一旦该任务有结果,立刻执行对应的回调函数
t_list.append(res) pool.shutdown()
for t in t_list:
print('>>>:', t.result())
'''
异步回调机制:当异步提交的任务有返回结果之后,会自动触发回调函数的执行
根据打印出的进程号,可以发现:
池子中创建的进程创建一次就不会再创建了
至始至终用的都是最初的那几个
这样的话节省开辟进程的资源
上述结论对线程同样适用
'''

二、协程

进程:资源单位
线程:执行单位
协程:单线程下实现并发
并发:切换+保存状态
ps:看起来像是同时运行的,就可以称之为并发
协程:完全是程序员自己意淫出来的名词
单线程下实现并发
并发的条件:多道技术
空间上的复用:共用同一套操作系统
时间上的复用:切换+保存状态
程序员自己通过代码自己检测程序中的IO
一旦遇到IO自己通过代码切换
给操作系统的感觉就是你这个线程没有任何的IO
ps:欺骗操作系统,让他误以为你这个程序一直没有IO
从而保证程序在运行态和就绪态来回切换
提升代码的运行效率
切换+保存状态就一定能够提升效率吗?
当你的任务是IO密集型的情况下 提升效率
如果你的任务是计算密集型的 降低效率
极限提升CPU工作效率的方式:
多进程下开多线程
多线程下再开协程
# 串行执行  1.5458002090454102
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) # 基于yield并发执行 2.3516733646392822
# yield可以保存上一次的结果
import time def func1():
while True:
10000000 + 1
yield def func2():
g = func1()
for i in range(10000000):
# time.sleep(100) # 模拟IO,yield并不会捕捉到并自动切换
i + 1
next(g) start = time.time()
func2()
stop = time.time()
print(stop - start)
'''
需要找到一个能够识别IO的一个工具————gevent模块,这是一个第三方模块,需要我们手动下载
'''
from gevent import monkey;monkey.patch_all()
from gevent import spawn
import time
'''
注意gevent模块没办法自动识别time.sleep()等IO情况
需要你手动再配置一个参数
from gevent import monkey;monkey.patch_all(),使spawn能够监测time.sleep()等IO
由于该模块经常使用,所以建议写成一行
''' def heng():
print('哼')
time.sleep(2)
print('哼') def ha():
print('哈')
time.sleep(3)
print('哈') def heiheihei():
print('嘿嘿嘿')
time.sleep(4)
print('嘿嘿嘿') start = time.time()
g1 = spawn(heng) # 对传入的函数名,加括号自动调用,并且监测其状态
g2 = spawn(ha)
g3 = spawn(heiheihei)
g1.join() # 等待任务运行完毕
g2.join()
g3.join()
print(time.time() - start) # 4.0027806758880615

三、通过协程实现TCP服务端并发

# 服务端
from gevent import monkey;monkey.patch_all()
from gevent import spawn
import socket server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5) def talk(conn):
while True:
try:
data = conn.recv(1024)
if len(data) == 0: break
print(data.decode('utf-8'))
conn.send(data.upper())
except ConnectionResetError as e:
print(e)
break
conn.close() def server1():
while True:
conn, addr = server.accept()
spawn(talk, conn) if __name__ == '__main__':
g1 = spawn(server1)
g1.join() # 客户端
import socket
from threading import Thread, current_thread def client1():
client = socket.socket()
client.connect(('127.0.0.1', 8080))
n = 0
while True:
data = f'{current_thread().name} {n}'
client.send(data.encode('utf-8'))
res = client.recv(1024)
print(res.decode('utf-8'))
n += 1 for i in range(400):
t = Thread(target=client1)
t.start()

进程池与线程池、协程、协程实现TCP服务端并发、IO模型的更多相关文章

  1. 8.14 day32 TCP服务端并发 GIL解释器锁 python多线程是否有用 死锁与递归锁 信号量event事件线程q

    TCP服务端支持并发 解决方式:开多线程 服务端 基础版 import socket """ 服务端 1.要有固定的IP和PORT 2.24小时不间断提供服务 3.能够支 ...

  2. 进程池与线程池基本使用、协程理论与实操、IO模型、前端、BS架构、HTTP协议与HTML前戏

    昨日内容回顾 GIL全局解释器锁 1.在python解释器中 才有GIL的存在(只与解释器有关) 2.GIL本质上其实也是一把互斥锁(并发变串行 牺牲效率保证安全) 3.GIL的存在 是由于Cpyth ...

  3. 05网络并发 ( GIL+进程池与线程池+协程+IO模型 )

    目录 05 网络并发 05 网络并发

  4. python系列之 - 并发编程(进程池,线程池,协程)

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  5. python并发编程之进程池,线程池,协程

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  6. Python 37 进程池与线程池 、 协程

    一:进程池与线程池 提交任务的两种方式: 1.同步调用:提交完一个任务之后,就在原地等待,等任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行 2.异步调用:提交完一个任务之后, ...

  7. 8.15 day33 进程池与线程池_协程_IO模型(了解)

    进程池和线程池 开进程开线程都需要消耗资源,只不过两者比较的情况线程消耗的资源比较少 在计算机能够承受范围之内最大限度的利用计算机 什么是池? ​ 在保证计算机硬件安全的情况下最大限度地利用计算机 ​ ...

  8. Event事件、进程池与线程池、协程

    目录 Event事件 进程池与线程池 多线程爬取梨视频 协程 协程目的 gevent TCP服务端socket套接字实现协程 Event事件 用来控制线程的执行 出现e.wait(),就会把这个线程设 ...

  9. 进程池和线程池、协程、TCP单线程实现并发

    一.进程池和线程池 当被操作对象数目不大时,我们可以手动创建几个进程和线程,十几个几十个还好,但是如果有上百个上千个.手动操作麻烦而且电脑硬件跟不上,可以会崩溃,此时进程池.线程池的功效就能发挥了.我 ...

随机推荐

  1. [CF]Round511

    这场比赛我及时的参加了,但是打的时候状态实在是太烂了,只做出来了Div2的AB题. A Little C loves 3 I 直接构造就行. B Cover Points 应该很容易就看出来这个等腰三 ...

  2. 如何在linux主机上运行/调试 arm/mips架构的binary

    如何在linux主机上运行/调试 arm/mips架构的binary 原文链接M4x@10.0.0.55 本文中用于展示的binary分别来自Jarvis OJ上pwn的add,typo两道题 写这篇 ...

  3. 什么是类的hashcode值

    1.要知道什么是类的hashcode值,首要要了解什么是hash(哈希).Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换 ...

  4. java+selenium打开浏览器实现后台静默运行

    简介:java selenium搭建无界面浏览器 PhantomJS是一个基于Webkit的"无界面"(headless)浏览器,它会把网站加载到内存并执行页面上的JavaScri ...

  5. Java实现JSONObject对象与Json字符串互相转换

    Java实现JSONObject对象与Json字符串互相转换 JSONObject 转 JSON 字符串 Java代码: JSONObject jsonObject = new JSONObject( ...

  6. How To Use These LED Garden Lights

    Are you considering the lighting options for the outdoor garden? Depending on how you use it, LED ga ...

  7. winform学习(2)窗体属性

    窗体也属于控件(controls) 主窗体:在Main函数中创建的窗体,当关闭主窗体时,整个程序也就关闭了. 如何打开控件属性面板: ①在该控件上单击鼠标右键--属性. ②选中该控件,按F4 窗体常用 ...

  8. APL: ANSYS Power Library

    1. creating accurate switching current waveforms (profiles) 2.output-state dependent decoupling capa ...

  9. springboot中配置addResourceHandler和addResourceLocations,使得可以从磁盘中读取图片、视频、音频等

    磁盘目录 WebMvcConfig的代码 //对静态资源的配置 @Override public void addResourceHandlers(ResourceHandlerRegistry re ...

  10. poj 2195 Going Home(最小费用流)

    题目链接:http://poj.org/problem?id=2195 题目大意是给一张网格,网格中m代表人,h代表房子,网格中的房子和人数量相等,人可以向上向下走,每走1步花费加1,每个房子只能住一 ...