• 协程


    一、协程

    1、协程:
    单线程实现并发(为了提高效率;但不是说所有协程都会提升效率)
    在应用程序里控制多个任务的切换+保存状态
    优点:
    应用程序级别速度要远远高于操作系统的切换
    缺点:
    多个任务一旦有一个阻塞没有切,整个线程都阻塞在原地
    该线程内的其他的任务都不能执行了

    一旦引入协程,就需要检测单线程下所有的IO行为,
    实现遇到IO就切换,少一个都不行,因为一旦一个任务阻塞了,整个线程就阻塞了,
    其他的任务即便是可以计算,但是也无法运行了

    2、有效的协程在一定程度‘骗过’了CPU;通过自己内部协调,一遇到IO就切到自己的其他程序中,
    使得CPU以为这个程序一直在运行,从而使其更有可能处于就绪态或运行态,以更多的占用CPU。

    实现并发的三种手段:
    a)单线程下的并发;由程序自己控制,相对速度快
    b)多线程下的并发;由操作系统控制,相对速度较慢
    c)多进程下的并发;由操作系统控制,相对速度慢

    3、协程序的目的:
    想要在单线程下实现并发
    并发指的是多个任务看起来是同时运行的
    并发=切换+保存状态

    yield、greenlet都无法实现遇到IO自动切换来提高效率 ,就用到了gevent模块


    from gevent import monkey,spawn;monkey.patch_all() #monkey.patch_all()打补丁(gevent)
    from threading import current_thread
    import time

    def eat():
    print('%s eat 1'%current_thread().name)
    time.sleep(3) # 直接调用gevent模块实现遇到IO切换+保持状态
    print('%s eat 2'%current_thread().name)

    def play():
    print('%s play 1'%current_thread().name)
    time.sleep(1)
    print('%s play 2 '%current_thread().name)

    start=time.time()
    g1=spawn(eat,) #spawn 默认为异步调用,如果不加time.sleep或 g.join(),spawn提交后不在原地等待执行,程序直接结束
    g2=spawn(play,)

    print(current_thread().name)
    g1.join()
    g2.join()
    print('主',time.time()-start)

    '''
    MainThread
    DummyThread-1 eat 1
    DummyThread-2 play 1
    DummyThread-2 play 2
    DummyThread-1 eat 2
    主 3.006171941757202
    '''
    本质是一个线程 (Dummy虚拟的,假的)


    二、并发的套接字通信

    服务端:
    from socket import *
    from gevent import spawn,monkey;monkey.patch_all()
    from threading import Thread

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

    print('start...')
    while True:
    conn,client_addr=server.accept()
    spawn(talk,conn,)

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


    客户端:
    from threading import Thread,current_thread
    from socket import *
    import os

    def task():
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))

    while True:
    msg='%s say hello' %current_thread().name
    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=task,)
    t.start()
  • 相关阅读:
    关于Django 报错 ImportError: cannot import name RegexUrlResolver解决
    Git版本控制
    java Labmda表达式
    java注解&反射
    maven
    数据库
    为什么java中子类重写父类的方法时声明抛出异常不能比父类范围大
    【Linux】Linux基本命令
    阿里云服务器linux环境搭建SSM项目(一)--Linux环境配置jdk和Tomcat.md
    阿里云服务器linux环境搭建SSM项目(二)--linux环境配置mysql5.7.md
  • 原文地址:https://www.cnblogs.com/kingyanan/p/9334787.html
Copyright © 2020-2023  润新知