• Day 36 socket并发,协程,进程池与线程池


    一、socket并发

    #服务端
    import
    socket from threading import Thread server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) def communcate(conn): while True: try: data = conn.recv(1024) if not data: break print(data) conn.send(data.upper()) except ConnectionResetError: break conn.close() while True: conn,addr=server.accept() print(addr) t=Thread(target=communcate,args=(conn,)) t.start()
    #客户端
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    
    
    while True:
        info = input(">>>:").encode('utf-8')
        if not info:continue
        client.send(info)
        data=client.recv(1024)
        print(data.decode('utf-8'))

    二、协程

    协程:
    进程:资源单位(车间)
    线程:最小执行单位(流水线)
    协程:单线程下实现并发

    并发:看上去像同时执行就可以称之为并发

    多道技术:
    空间上的复用
    时间上的复用
    核心:切换+保存状态
    协程:完全是我们高技术的人自己编出来的名词
    通过代码层面自己监测io自己实现切换,让操作系统误认为
    你这个线程没有io

    切换+保存状态就一定能够提升你程序的效率吗?
    不一定
    当你的任务是计算密集型,反而会降低效率
    如果你的任务是IO密集型,会提升效率
    协程:单线程下实现并发
    如果你能够自己通过代码层面监测你自己的io行为
    并且通过代码实现切换+保存状态
    串行执行纯计算操作
    import time
    def task1():
        res =1
        for i in range(1000000):
            res+=i
    
    def task2():
        res=1
        for i in range(1000000):
            res*=i
    
    stat=time.time()
    task1()
    task2()
    stop =time.time()
    print(stop-stat)
    计算一段时间往上切,加上了来回切的时间
    基于yiel保存状态,实现两个任务间来回切换,实现并发效果
    yield并不能帮我们自动捕获到io行为才切换
    import time
    def task1():
        res =1
        for i in range(1000000):
            res+=i
            yield
    
    def task2():
        g=task1()
        res=1
        for i in range(1000000):
            res*=i
            next(g)
    
    stat=time.time()
    
    task2()
    stop =time.time()
    print(stop-stat)

    三、gevent模块

    一个spawn就是一个帮你管理任务的对象
    gevent模块不能识别它本身以外的所有的IO行为比如(time.sleep)
    from gevent import monkey;monkey.patch_all()  #能够帮助我们识别所有的IO行为
    from threading import current_thread
    import gevent
    import time
    def eat():
        print('%s eat 1'%current_thread().name)
        # gevent.sleep(3)
        time.sleep(3)
        print('%s eat 2'%current_thread().name)
    def play():
        print('%s play 1'%current_thread().name)
        # gevent.sleep(5)
        time.sleep(5)
        print('%s play 2'%current_thread().name)
    
    g1 =gevent.spawn(eat) #异步提交
    g2 =gevent.spawn(play)
    print(current_thread().name)
    
    g1.join()
    g2.join()

    四、进程池与线程池

    1、为什么要用“池”:
    池子是用来限制并发的任务数目,限制我们的计算机在一个自己承受的范围内去并发的执行任务
    2、什么时候用进程池:
    并发的任务属于计算密集型
    3、什么时候用线程池:
    并发的任务属于IO密集型
    
    
    #进程池
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    import time,os,random
    
    def task(x):
        print('%s 接客'%os.getpid())
        time.sleep(random.randint(2,3))
        return x**2
    if __name__ == '__main__':
        p =ProcessPoolExecutor(max_workers=4) #默认开启进程数是cpu的核数
        for i in range(20):
            p.submit(task,i) #submit提交任务的方式,异步提交
    
    
    #线程池
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    import time,os,random
    
    def task(x):
        print('%s 接客'%x)
        time.sleep(random.randint(2,3))
        return x**2
    if __name__ == '__main__':
        p =ThreadPoolExecutor(4) #默认开启(线程数=cpu核数*5左右)
        for i in range(20):
            p.submit(task,i) #submit提交任务的方式,异步提交

    五、单线程下实现并发

    #服务端
    from gevent import monkey;monkey.patch_all()
    from gevent import spawn
    import socket
    
    def communicate(conn):
        while True:
            try:
                data =conn.recv(1024)
                if not data: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()
     
     
     
     
  • 相关阅读:
    总有一天你将破蛹而出
    java 连接 Access数据库的两种方法
    freemarker中页面直接可以使用的内置对象
    freemarker中页面直接可以使用的内置对象
    常见的样式
    ibatis常用的集中判断语句
    mysql类型转换
    ibatis常用的集中判断语句
    window.open打开窗口时父窗口变成object
    window.open打开窗口时父窗口变成object
  • 原文地址:https://www.cnblogs.com/zhengyuli/p/10840962.html
Copyright © 2020-2023  润新知