37 协程

协程

进程:资源单位程序员

线程:执行单位web

协程:单线程下实现并发(可以在多个任务之间切换和保存状态来节省IO)多线程

多道技术: 并发

  空间上的复用 异步

  时间上的复用socket

核心:切换+保存状态ide

注意:高并发

  操做系统的切换+保存状态是针对多个线程,spa

  想在单个线程下本身手动实现操做系统的切换+保存状态的功能,协程产生操作系统

  因为协程是程序员本身想出来并实现,它对于操做系统来讲根本不存在。操做系统只知道进程和线程。

  须要注意的是:并非单个线程下实现切换+保存状态就能提高效率,可能没有遇到io也切,那反而会下降效率

    任务是计算密集型,反而会下降效率

    任务是IO密集型,会提高效率

将单个线程的效率提高到最高,多进程下开多线程,多线程下用协程>>> 实现高并发!!! 

  1)yield可以实现保存上次运行状态,可是没法识别io

# 串行执行
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并发执行
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)
切换➕保存状态

2)单线程下实现并发

若是你可以本身经过代码层面监测你本身的io行为
而且经过代码实现切换+保存状态
单线程实现高并发
# ---------------服务端---------------------
from gevent import monkey; monkey.patch_all()
from gevent import spawn
import socket


def communicate(conn):
    while True:
        try:
            data = conn.recv(1024)
            if len(data) == 0: break
            print(data.decode('utf-8'))
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()


def server():
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    while True:
        conn, addr = server.accept()
        spawn(communicate, conn)


if __name__ == '__main__':
    s1 = spawn(server)
    s1.join()



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


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


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

3)gevent模块的使用

  spawn:帮你管理任务的对象

  gevent模块不能识别它自己之外的全部的IO行为,可是它内部封装了一个模块,可以帮助咱们识别全部的IO行为

 

from gevent import monkey; 
monkey.patch_all()  # 监测代码中全部io行为
from gevent import spawn
# gevent自己识别不了time.sleep等不属于该模块内的io操做
import time


def heng(name):
    print('%s 哼' % name)
    time.sleep(2)
    print('%s 哼' % name)


def ha(name):
    print('%s 哈' % name)
    time.sleep(3)
    print('%s 哈' % name)


start = time.time()
s1 = spawn(heng, 'Tom')
s2 = spawn(ha, 'Bob')

s1.join()
s2.join()
# heng('Tom')
# ha('Bob')

print('', time.time() - start)

 4)协程实现服务端客户端通讯:socket并发

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


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

def server(ip, port, backlog=5):
    server = socket(AF_INET, SOCK_STREAM)
    server.bind((ip, port))
    server.listen(backlog)

    while True:  # 连接循环
        conn, client_addr = server.accept()
        print(client_addr)

        # 通讯
        spawn(communicate,conn)


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

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


def client():
    client = socket(AF_INET, SOCK_STREAM)
    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=client)
        t.start()

5)IO模型 

阻塞IO  Blocking I/O非阻塞IO  服务端通讯针对accept用s.setblocking(False)加异常捕获,cpu占用率太高IO多路复用 multiplexing I/O  在只检测一个套接字的状况下,他的效率连阻塞IO都比不上。由于select这个中间人增长了环节。  可是在检测多个套接字的状况下,就能省去wait for data过程异步IO  Asynchronous I/O
相关文章
相关标签/搜索