第三篇:协程

协程的介绍

"""
进程:资源单位
线程:执行单位
协程:单线程下实现并发(这个概念完全是由程序员意淫出来的,根本不存在)
    程序员在代码层面上检测所有的IO操作,一旦遇到IO,将在代码级别完成切换
    这样给CPU的感觉是这个程序一直运行,没有IO,从而提升程序的运行效率

多道技术
    切换+保存状态
    CPU两种切换(1.程序遇到IO  2.程序长时间占用)

代码如何做到切换+保存状态
    切换
        切换不一定提高效率,也可能降低效率
        IO切          提升
        没有IO切    降低
    保存状态
        保存上一次执行的状态,下一次来接着执行上一次的操作继续往后执行
        yield  
"""

验证切换是否一定能提高效率

# 串行执行计算密集型任务    0.5209994316101074
import time
def func1():
    for i in range(10000000):
        i + 1

def func2():
    for i in range(10000000):
        i + 1

start_time = time.time()
func1()
func2()
print(time.time() - start_time)


# 切换 + yield    0.7936575412750244
import time
def func1():
    while True:
        10000000 + 1
        yield

def func2():
    g = func1()  # 先初始化出生成器
    for i in range(10000000):
        i + 1
        next(g)

start_time = time.time()
func2()
print(time.time() - start_time)

 

gevent模块(了解)

安装:pip3 install gevent

from gevent import monkey;monkey.patch_all()
import time
from gevent import spawn

'''
gevent模块本身无法检测常见的一些io操作
在使用的时候需要你额外的导入一句话
from gevent import monkey
monkey.patch_all()
由于上面的两句话在使用gevent模块的时候是肯定要导入的,支持简写
from gevent import monkey;monkey.patch_all()
'''

def heng():
    print('')
    time.sleep(2)
    print('')
def ha():
    print('')
    time.sleep(3)
    print('')
def heiheihei():
    print('heiheihei')
    time.sleep(3)
    print('heiheihei')
start_time = time.time()
g1 = spawn(heng)
g2 = spawn(ha)
g3 = spawn(heiheihei)
g1.join()
g2.join()
g3.join()
print(time.time() - start_time)  # 3.109663963317871

 

协程实现TCP服务端的并发

# 服务端
from gevent import monkey;monkey.patch_all()
import socket
from gevent import spawn

def communication(conn):
    while True:
        try:
            data = conn.recv(1024)
            if len(data) == 0: break
            conn.send(data.upper())
        except ConnectionResetError as e:
            print(e)
            break
    conn.close()

def server(ip, port):
    server = socket.socket()
    server.bind((ip, port))
    server.listen(5)
    while True:
        conn, addr = server.accept()
        spawn(communication, conn)

if __name__ == '__main__':
    g1 = spawn(server, '127.0.0.1', 8080)
    g1.join()

# 客户端
from threading import Thread, current_thread
import socket

def x_client():
    client = socket.socket()
    client.connect(('127.0.0.1',8080))
    n = 0
    while True:
        msg = '%s say hello %s'%(current_thread().name,n)
        n += 1
        client.send(msg.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))

if __name__ == '__main__':
    for i in range(500):
        t = Thread(target=x_client)
        t.start()

 

理想状态:

 我们可以通过多进程下面开设多线程,多线程下面开设协程程序,从而使我们的程序执行效率提高

posted @ 2023-02-16 10:37  猿小姜  阅读(19)  评论(0编辑  收藏  举报