zoukankan      html  css  js  c++  java
  • 线程池与进程池,同步异步,Event事件

    线程池与进程池

    池:容器

    1. 用来避免频繁的创建和销毁(进程/线程)所带来的资源开销
    2. 可以限制同时存在的线程数量,以保证服务器不会因为资源不足而导致崩溃
    3. 帮我们管理了线程的生命周期
    4. 管理了任务的分配
    import os
    import time
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from threading import activeCount,enumerate,currentThread
    
    # # 创建一个线程池,默认是(CPU核心数或者1) * 5
    # pool = ThreadPoolExecutor(2)	# 这里指定最多可以容纳两个线程
    #
    # def task():
    #     print(currentThread().name)
    #
    # # 提交任务到池子中
    # pool.submit(task)		# 传参直接在后面接逗号然后填参数就可以
    # pool.submit(task)
    
    # pool.shutdown()	# 关闭这个线程池,会一直阻塞到所有任务执行完毕
    
    
    def task():
        time.sleep(1)
        print(os.getpid())
    
    
    if __name__ == '__main__':
        # 创建一个进程池,默认是CPU核心数或者1
        pool = ProcessPoolExecutor(2)	# 这里指定最多可以容纳两个进程
        pool.submit(task)
        pool.submit(task)
        pool.submit(task)
    

    思考:不用线程池,创造线程池

    如果进程不结束,那么进程池/线程池中的进程/线程就会一直存活

    同步异步

    名称 类型
    阻塞 非阻塞 程序的状态
    串行 并发 并行 程序处理任务的方式
    同步 异步 程序提交任务的方式

    同步

    • 提交任务后必须在原地等待,直到任务结束
      • 程序卡住了,但不是阻塞,因为没有进入IO,而是在进行大量的计算

    异步

    • 提交任务后不需要在原地等待 可以继续往下执行代码 (进程/线程)

    异步效率高于同步 ,异步任务将导致一个问题,就是任务的发起方不知道任务何时处理完毕

    解决方法

    1. 轮询:每隔一段时间就问一次
      • 效率低,无法及时获得结果,不推荐
    2. 让任务的执行方主动通知(异步回调)
      • 可以及时拿到任务的结果,推荐
      • 异步回调案例
    # 异步回调
    from threading import Thread
    # 具体的任务
    def task(callback):
        print("run")
        for i in range(100000000):
            1+1
        callback("ok")	# 这样写很灵活
       
    
    #回调函数 参数为任务的结果
    def finished(res):
        print("任务完成!",res)
    
    
    print("start")
    t = Thread(target=task,args=(finished,))
    t.start()  #执行task时 没有导致主线程卡主 而是继续运行
    print("over")
    

    线程池中回调的使用

    from 
    # 使用案例:
    def task(num):
        time.sleep(1)
        print(num)
        return "hello python"
    
    def callback(obj):
        print(obj.result())
    
    
    pool = ThreadPoolExecutor()
    res = pool.submit(task, 123)
    # print(res.result())	# result是阻塞的,会直到拿到返回值才会释放
    
    res.add_done_callback(callback)	# 为这个函数绑定回调函数
    print("over") 
    

    Event事件

    线程间状态同步

    把一个任务丢到子线程中,这个任务将异步执行,那如何获取到这个任务的执行状态

    (执行状态和执行结果不是一个概念)

    如果需要拿到执行结果,可以采用异步回调

    假设

    一个线程 负责启动服务器 **启动服务器需要花一定的时间 **

    另一个线程作为客户端 要连接服务器 **必须保证服务器已经启动 **

    要获取状态可以采用轮询的方法 但是浪费了CPU资源 而且可能会造成延迟 不能立即获取状态

    就可以使用事件来完成状态同步

    事件本质就是 一个标志 可以是False 或是True

    特殊之处在于 其包含一个wait函数 可以阻塞当前线程 直到状态从False变为True

    • 轮询
    from threading import Thread
    import time
    
    # 轮询
    is_bool = False	# 轮询
    
    def start_server():
        global is_bool
        print("starting server......")
        time.sleep(3)
        print("server started!")
        is_bool = True	 # 修改事件的值为Tru
    
    def connect_server():
        while True:		
            if is_bool:
                print('连接服务器成功')
                break
            else:
                print('失败,服务器未启动')
                # 死循环一直循环占用CPU资源,所以sleep一小会。
                # 不sleep又占用资源,sleep了又不能立即获取状态
                time.sleep(0.5)	
                
    t1 = Thread(target=start_server)
    t2 = Thread(target=connect_server)
    
    t1.start()
    t2.start()
    
    • 异步回调
    from threading import Thread,Event
    import time
    
    e = Event()		# 刚创建时flag为False
    
    
    def start_server():
    
        print("starting server......")
        time.sleep(3)
        print("server started!")
       
        e.set()		# 将flag变成True,另外clear是把flag变成False
    
    
    def connect_server():
        e.wait() # 阻塞,等待事件从False 变为true
        
        if e.is_set():	# 获取当前flag状态
            print("连接服务器成功!")
    
    t1 = Thread(target=start_server)
    t2 = Thread(target=connect_server)
    
    t1.start()
    t2.start()
    
  • 相关阅读:
    学习总结
    HBase简要介绍
    分布式文件系统HDFS
    Hadoop基础安装和使用
    大数据的学习基础
    学习总结
    Python-爬取豆瓣电影信息并存到mysql
    python爬虫回顾与总结
    正则表达式-爬虫获取豆瓣电影超链接
    BeautifulSoup相关学习
  • 原文地址:https://www.cnblogs.com/lucky75/p/11140601.html
Copyright © 2011-2022 走看看