• 协程


     协程,自己控制cpu在多任务中切换,即单线程实现并发任务。单线程无法实现并行,但可实现并发。

    协程:是一种用户态的轻量级线程,即协程是由用户程序自己控制调度。

    优点:

    切换开销更小

    单线程内可以实现并发效果,最大限度利用cpu

    缺点:

    协程无法利用多核

    协程为单个线程,一旦阻塞则阻塞整个线程

    总结:

    必须在只有一个单线程里实现并发

    修改数据不用加锁

    用户程序里自己保存多个控制流的上下文栈

    yeild实现纯计算对比:

    #并发
    def producer():
        g=consumer()
        next(g)
        for i in range(10000):
            print("producer")
            g.send(i)
    
    def consumer():
        while True:
            res=yield
            print("consumer")
    import time
    start_time=time.time()
    producer()
    print(time.time()-start_time)

    #串行
    def producer():
        res=[]
        for i in range(10000):
            print("producer")
            res.append(i)
    
    def consumer(res):
        pass
    import time
    start_time=time.time()
    producer()
    print(time.time()-start_time)

    协程,降低I/O阻塞,提高利用率

     greenlet模块,实现多模块之间切换,多任务I/O密集型使用。

    #pip3 install greenlet
    from greenlet import greenlet
    def eat(name):
        print("%s eat 1" % name)
        g2.switch("ya")
        print("%s eat 2" % name)
        g2.switch()
    def play(name):
        print("%s play 1" % name)
        g1.switch()
        print("%s play 2" % name)
        g1.switch()
    g1=greenlet(eat)
    g2=greenlet(play)
    g1.switch("ya")

    gevent模块

    默认为异步提交

    import gevent,time
    from gevent import monkey
    monkey.patch_all()#监控所有I/O操作,否则只能识别sleep()
    def eat(name):
        print("%s eat 1" % name)
        gevent.sleep(3)
        print("%s eat 2" % name)
    def play(name):
        print("%s play 1" % name)
        gevent.sleep(5)
        print("%s play 2" % name)
    start_time=time.time()
    g1=gevent.spawn(eat,"ya")
    g2=gevent.spawn(play,"ya")
    g1.join()
    g2.join()
    print(time.time()-start_time)

    gevent模块异步提交任务,join(),保证主线程等待任务执行完毕

    也可以用joinall()方法

    gevent.joinall([g1,g2])

    gevent协程实现套接字

     server:

    from socket import *
    from gevent import monkey,spawn;monkey.patch_all()
    def talk(conn):
        print(conn)
        while True:
            try:
                print("recv")
                data=conn.recv(1024)
                if not data:
                    break
                conn.send(data.upper())
            except ConnectionResetError:
                break
        conn.close()
    def server(ip,port):
        server=socket(AF_INET,SOCK_STREAM)
        # server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
        server.bind((ip,port))
        server.listen(5)
        while True:
            conn,addr=server.accept()
            spawn(talk,conn)
        server.close()
    if __name__ == "__main__":
        g=spawn(server,"127.0.0.1",8080)
        g.join()
    View Code

    client:

    from threading import Thread,currentThread
    from socket import *
    def client():
        client=socket(AF_INET,SOCK_STREAM)
        client.connect(("127.0.0.1",8080))
        while True:
            client.send(("%s say hello" % currentThread().getName()).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()
    View Code
  • 相关阅读:
    google搜索技巧
    sqlite,mysql,access对比
    【转】python技术博客
    2013待阅读书目
    【转】larbin的代码实现逻辑概述
    【转】python遍历文件夹和文件
    【转】正则表达式高级讲解
    Atitit.mybatis的测试  以及spring与mybatis在本项目中的集成配置说明
    Atitit.100% 多个子元素自适应布局属性
    atitti.atiNav 手机导航组件的设计
  • 原文地址:https://www.cnblogs.com/yaya625202/p/9049141.html
Copyright © 2020-2023  润新知