zoukankan      html  css  js  c++  java
  • 进程池 协程 与I/O模型

    一.进程池与线程池

    进程池:限制进程创建的数量,使用时直接从进程池,获取空闲进程去执行任务,减少创建和销毁进程带来的时间消耗;如果进程的数量没有达到最大数量,且没有空闲进程去执行      任务,就会再创建一个新的进程,放入进程池去执行任务;

        如果进程池中的进程数量达到最大数量,没有空闲进程去,这是任务需要等待某个进程成为空闲进程之后,再去执行任务。

    from concurrent.futures import ProcessPoolExecutor
    
    import time
    import os
    
    # 池子中创建的进程/线程创建会被保存在进程/线程池中
    # 会调用进程/线程池中的进程/线程去执行任务
    # 节省了反复开辟进程/线程的资源
    pool = ProcessPoolExecutor()  # 默认是当前计算机cpu的个数
    
    def task(n):
        print(n,os.getpid())  # 查看当前进程号
        time.sleep(2)
    
    
    if __name__ == '__main__':
    
        for i in range(20):
            res = pool.submit(task,i)
    View Code

    ps:当进程池满后,没有kill进程的情况下,会使用进程池中的进程去执行任务,不会再去创建新的进程。

    线程池:同进程池概念类似。

    from concurrent.futures import ThreadPoolExecutor
    
    import time
    
    
    # 池子中创建的进程/线程创建会被保存在进程/线程池中
    # 会调用进程/线程池中的进程/线程去执行任务
    # 节省了反复开辟进程/线程的资源
    pool = ThreadPoolExecutor(5)  # 括号内可以传参数指定线程池内的线程个数
    # 也可以不传  不传默认是当前所在计算机的cpu个数乘5
    
    def task(n):
        print(n)  # 查看当前进程号
        time.sleep(2)
    
    
    for i in range(20):
        res = pool.submit(task,i)
    View Code

    进程异步:

    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    import time
    import os
    
    
    pool = ProcessPoolExecutor()  # 默认是当前计算机cpu的个数
    
    # 池子中创建的进程/线程创建会被保存在进程/线程池中
    # 会调用进程/线程池中的进程/线程去执行任务
    # 节省了反复开辟进程/线程的资源
    
    def task(n):
        print(n,os.getpid())  # 查看当前进程号
        time.sleep(2)
        return n**2
    
    
    def call_back(n):
        print('拿到了异步提交任务的返回结果:',n.result())
    """
    提交任务的方式
        同步:提交任务之后 原地等待任务的返回结果 期间不做任何事
        异步:提交任务之后 不等待任务的返回结果  通过回调方式获得异步返回值 直接执行下一行代码
    """
    
    """
    异步回调机制:当异步提交的任务有返回结果之后,会自动触发回调函数的执行
    
    """
    if __name__ == '__main__':
    
        t_list = []
        for i in range(20):
            res = pool.submit(task,i).add_done_callback(call_back)  # 提交任务的时候 绑定一个回调函数 一旦该任务有结果 立刻执行对于的回调函数
       
            t_list.append(res)
    View Code

    线程异步:

    from concurrent.futures import ThreadPoolExecutor
    import time
    import os
    
    pool = ThreadPoolExecutor(5)  # 括号内可以传参数指定线程池内的线程个数
    
    
    def task(n):
        print(n,os.getpid())  # 查看当前进程号
        time.sleep(2)
        return n**2
    
    
    def call_back(n):
        print('拿到了异步提交任务的返回结果:',n.result())
    
    # 异步回调机制:当异步提交的任务有返回结果之后,会自动触发回调函数的执行
    
    
    
    for i in range(20):
        res = pool.submit(task,i).add_done_callback(call_back)  # 提交任务的时候 绑定一个回调函数 一旦该任务有结果 立刻执行对于的回调函数
    View Code

    二.协程

    协程(Coroutine):是单线程下的并发,又称微线程。

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

     协程的本质 :就是在单线程下,由用户自己控制一个任务遇到io阻塞了就切换另外一个任务去执行,以此来提升效率。

    优点:

    1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级

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

    缺点:

    1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程

    2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

    单线程多协程TCP

    服务端

    from gevent import monkey;monkey.patch_all()
    import socket
    from gevent import spawn
    
    
    server = socket.socket()
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    
    
    def talk(conn):
        while True:
            try:
                data = conn.recv(1024)
                if len(data) == 0:break
                print(data.decode('utf-8'))
                conn.send(data.upper())
            except ConnectionResetError as e:
                print(e)
                break
        conn.close()
    
    def server1():
        while True:
            conn, addr = server.accept()
            spawn(talk,conn)
    
    if __name__ == '__main__':
        g1 = spawn(server1)
        g1.join()
    View Code

    客户端

    import socket
    from threading import Thread,current_thread
    
    
    def client():
        client = socket.socket()
        client.connect(('127.0.0.1',8080))
        n = 0
        while True:
    
            data = '%s %s'%(current_thread().name,n)
            client.send(data.encode('utf-8'))
            res = client.recv(1024)
            print(res.decode('utf-8'))
            n += 1
    
    for i in range(400):
        t = Thread(target=client)
        t.start()
    View Code

    三.I/O模型

  • 相关阅读:
    浅谈python socket编程
    MYSQL(三)
    python数据库操作之pymysql模块和sqlalchemy模块(项目必备)
    MYSQL(二)
    ajax应用篇
    浅析tornado web框架
    CSS学习笔记06 简单理解line-height
    CSS学习笔记05 display属性
    CSS学习笔记04 CSS文字排版常用属性
    CSS学习笔记03 CSS层叠性、继承性、特殊性
  • 原文地址:https://www.cnblogs.com/Cpsyche/p/11360078.html
Copyright © 2011-2022 走看看