zoukankan      html  css  js  c++  java
  • 进程池和线程池

    一、线程queue

    Python中,队列是线程间最常用的交换数据的形式。Queue模块是提供队列操作的模块

    import queue
    q = queue.Queue()
    q.put('123')
    q.put('qwe')
    print(q.get())
    print(q.get())
    print(q.get())
    q.task_done()
    q.join()
    
    q = queue.LifoQueue()  # 堆栈 先进后出
    q.put('123')
    q.put('456')
    q.put('789')
    print(q.get())
    print(q.get())
    print(q.get())
    #  789  456  123
    
    q = queue.PriorityQueue()  # 可以根据优先级取数据
    # 通常这个元组的第一个值是int类型
    q.put((50, 'x'))
    q.put((80, 'y'))
    q.put((1, 'z'))
    print(q.get())
    print(q.get())
    print(q.get())
    

    二、线程定时器

    from threading import Thread, Timer
    import time
    
    def task():
        print('线程执行了')
        time.sleep(2)
        print('线程结束了')
        
    t = Timer(4, task)  # 过了4s后开启了一个线程
    t.start()
    

    三、进程池和线程池

    进程池线程池

    • 池的功能:限制进程数或线程数

    • 什么时候限制:当并发的任务数量远远大于计算机所能承受的范围,即无法一次性开启过多的任务数量(我就应该考虑去限制我进程数或线程数,从而保证服务器不崩)

    同步:提交了一个任务,必须等任务执行完了(拿到返回值),才能执行下一行代码

    异步:提交了一个任务,不要等执行完了,可以直接执行下一行代码

    from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
    from threading import currentThread
    from multiprocessing import current_process
    import time
    
    def task(i):
        print(f'{currentThread().name} 在执行任务 {i}')
        # print(f'进程 {current_process().name} 在执行任务 {i}')
        time.sleep(1)
        return i**2
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(4) # 池子里只有4个线程
        # pool = ProcessPoolExecutor(4) # 池子里只有4个线程
        fu_list = []
        for i in range(20):
            # pool.submit(task,i) # task任务要做20次,4个线程负责做这个事
            future = pool.submit(task,i) # task任务要做20次,4个进程负责做这个事
            # print(future.result()) # 如果没有结果一直等待拿到结果,导致了所有的任务都在串行
            fu_list.append(future)
        pool.shutdown() # 关闭了池的入口,会等待所有的任务执行完,结束阻塞.
        for fu in fu_list:
            print(fu.result())
    
    
    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    from threading import currentThread
    from multiprocessing import current_process
    import time
    
    def task(i):
        print(f'{currentThread().name} 在执行任务 {i}')
        # print(f'进程 {current_process().name} 在执行任务 {i}')
        time.sleep(1)
        return i**2
    
    
    def parse(future):
        # 处理拿到的结果
        print(future.result())
    
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(4) # 池子里只有4个线程
        # pool = ProcessPoolExecutor(4) # 池子里只有4个线程
        fu_list = []
        for i in range(20):
            # pool.submit(task,i) # task任务要做20次,4个线程负责做这个事
            future = pool.submit(task,i) # task任务要做20次,4个进程负责做这个事
            future.add_done_callback(parse)
            # 为当前任务绑定了一个函数,在当前任务执行结束的时候会触发这个函数,
            # 会把future对象作为参数传给函数
            # 这个称之为回调函数,处理完了回来就调用这个函数.
    
    
            # print(future.result()) # 如果没有结果一直等待拿到结果,导致了所有的任务都在串行
    
        # pool.shutdown() # 关闭了池的入口,会等待所有的任务执行完,结束阻塞.
        # for fu in fu_list:
        #     print(fu.result())
    

    四、协程

    Python的线程用的是操作系统原生的线程

    协程:单线程下实现并发

    ​ -并发:切换+保存状态
    ​ -多线程:操作系统帮你实现的,如果遇到io切换,执行时间过长也会切换,实现一个雨露均沾的效果。

    什么样的协程是有意义的

    ​ -遇到io切换的时候才有意义

    ​ -具体:协程概念本质是程序员抽象出来的,操作系统根本不知道协程存在,也就是说来了一个线程我自己遇到io,我自己线程内部直接切到自己的别的任务上了,操作系统根本发现不了,也就是实现了单线程下效率最高.

    ​ -优点:自己控制切换要比操作系统切换快的多

    ​ -缺点:对比多线程:自己要检测所有的io,但凡有一个阻塞整体都跟着阻塞;

    ​ 对比对进程:无法利用多核优势。

    为什么要有协程(遇到io切换)?

    ​ -自己控制切换要比操作系统切换快的多,降低了单个线程的io时间。

    import time
    def func1():
        while True:
            1000000+1
            yield
    
    def func2():
        g = func1()
        for i in range(100000000):
            i+1
            next(g)
    
    start = time.time()
    func2()
    stop = time.time()
    print(stop - start) # 14.774465560913086
    

    第三方模块实现协程

    from gevent import monkey;monkey.patch_all() #打了一个补丁,可以实现捕获非gevent的io.
    import gevent
    
    import time
    def eat():
        print('eat 1')
        time.sleep(2)
        print('eat 2')
    def play():
        print('play 1')
        # 疯狂的计算呢没有io
        time.sleep(3)
        print('play 2')
    
    start = time.time()
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    g1.join()
    g2.join()
    end = time.time()
    print(end-start) # 3.0040290355682373
    
  • 相关阅读:
    jquery基本操作笔记
    unity 读取灰度图生成三维地形并贴图卫星影像
    unity 读取灰度图生成按高程分层设色地形模型
    opengl读取灰度图生成三维地形并添加光照
    opengl鼠标键盘控制相机漫游
    opengl球形网格生成
    opengl读取灰度图生成三维地形
    unity三维地球模型生成
    ue4读取灰度图生成三维地形mesh
    unity读取灰度图生成等值线图
  • 原文地址:https://www.cnblogs.com/17vv/p/11549995.html
Copyright © 2011-2022 走看看