zoukankan      html  css  js  c++  java
  • 进程池线程池与单程下实现并发

    一、 socket并发(进程线程池铺垫)

     服务端:

    import socket
    from threading import Thread
    """
    服务端:
    1.固定的ip和port
    2.24小时不间断提供服务
    3.支持高并发
    """
    server = socket.socket()
    server.bind(('127.0.0.1',8080))
    server.listen(5) # 半连接池
    
    
    def communicate(conn):
    while True:
    try:
    data = conn.recv(1024) # 阻塞
    if len(data) == 0:break
    print(data)
    conn.send(data.upper())
    except ConnectionResetError:
    break
    conn.close()
    
    while True:
    conn,addr = server.accept() # 阻塞
    print(addr)
    t = Thread(target=communicate,args=(conn,))
    t.start()
    View Code

     客户端:

    import socket
    
    
    client = socket.socket()
    client.connect(('127.0.0.1',8080))
    
    while True:
        info = input('>>>:').encode('utf-8')
        if len(info) == 0:continue
        client.send(info)
        data = client.recv(1024)
        print(data)
    View Code

    二 、 进程池线程池

    如一中的socket并发,假如客户端的数量呈万级甚至百万千万级时,此时cup恐怕要冒烟了,那怎么样能解决同一时间的超大高并发呢?进程池和线程池能够解决

    说在前面:无论是开线程还是开进程其实都消耗资源,开线程消耗的资源比开进程的小。

    池:

        为了减缓计算机硬件的压力,避免计算机硬件设备崩溃

        虽然减轻了计算机硬件的压力,但是一定程度上降低了持续的效率

    进程池线程池:

        为了限制开设的进程数和线程数,从而保证计算机硬件的安全

    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    import time
    import os
    
     
    
    # 示例化池对象
    # 不知道参数的情况,默认是当前计算机cpu个数乘以5,也可以指定线程个数
    pool = ProcessPoolExecutor(5) # 创建了一个池子,池子里面有20个线程
    
    
    def task(n):
    print(n,os.getpid())
    time.sleep(2)
    return n**2
    
    
    def call_back(n):
    print('我拿到了结果:%s'%n.result())
    """
    提交任务的方式
    同步:提交任务之后,原地等待任务的返回结果,再继续执行下一步代码
    异步:提交任务之后,不等待任务的返回结果(通过回调函数拿到返回结果并处理),直接执行下一步操作
    """
    
    
    # 回调函数:异步提交之后一旦任务有返回结果,自动交给另外一个去执行
    if __name__ == '__main__':
    # pool.submit(task,1)
    t_list = []
    for i in range(20):
    future = pool.submit(task,i).add_done_callback(call_back) # 异步提交任务
    t_list.append(future)
    
    # pool.shutdown() # 关闭池子并且等待池子中所有的任务运行完毕
    # for p in t_list:
    # print('>>>:',p.result())
    print('')
    View Code

    三 、 协程

    学习协程前的铺垫:

    进程:资源单位(车间)

    线程:最小执行单位,即CPU的执行单位(流水线)

    协程:单线程下实现并发

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

    多道技术:

        空间上的复用

        时间上的复用

    核心:切换+保存状态

    协程:完全就是高技术的人自己意淫出来的,但是没想到还挺好用

        通过代码层面自己检测 io 自己实现切换,让操作系统误以为你这个线程没有 io

        实现原理就是:通过代码实现切换+保存状态

        运用范围:单线程实现高并发

    开多进程

    多个进程下面再开多线程

    多个线程下开协程

    实现高并发

    gevent 模块的使用(genvet就是用来实现类似切换+保存效果)

    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,'egon')
    s2 = spawn(ha,'echo')
    
    s1.join()
    s2.join()
    # heng('egon')
    # ha('kevin')
    
    print('',time.time()-start)
    View Code

    用 gevent 模块实现网络通信的单线程高并发

    服务端

    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()
    View Code

    客户端

    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()
    View Code

    四 、IO模型初识

    上海张江第一帅元少对于 IO 模块的理解:

    https://www.cnblogs.com/Dominic-Ji/p/10806351.html

  • 相关阅读:
    第一个反汇编程序
    边缘网关协议(BGP)
    Servlet 学习小结之doPost()方法和doGet()方法
    extern "C"
    工欲善其事 必先利其器
    我是一个混蛋程序员
    KMP 算法——C
    二分查找——C语言
    大整数加法——C语言
    子字符串查找——C语言
  • 原文地址:https://www.cnblogs.com/SlookUp/p/10839740.html
Copyright © 2011-2022 走看看