concurrent模块

1、concurrent模块的介绍

  • concurrent.futures模块提供了高度封装的异步调用接口
    • ThreadPoolExecutor:线程池,提供异步调用
    • ProcessPoolExecutor:进程池,提供异步调用

ProcessPoolExecutor 和 ThreadPoolExecutor:两者都实现相同的接口,该接口由抽象Executor类定义。

python并发编程--进程&线程--其他模块-从菜鸟到老鸟(三)

2、基本方法

使用_base.Executor

concurrent.futures.thread.ThreadPoolExecutor    #线程池
concurrent.futures.process.ProcessPoolExecutor  #进程池
#构造函数
  def __init__(self, max_workers=None, mp_context=None,
               initializer=None, initargs=()):
  • submit(fn, *args, **kwargs) :异步提交任务

    使用submit函数来提交线程需要执行任务(函数名和参数)到线程池中,并返回该任务的句柄(类似于文件、画图),注意submit()不是阻塞的,而是立即返回。

  • map(func, *iterables, timeout=None, chunksize=1)

    取代for循环submit的操作

  • shutdown(wait=True) :相当于进程池的pool.close()+pool.join()操作
    • wait=True,等待池内所有任务执行完毕回收完资源后才继续
    • wait=False,立即返回,并不会等待池内的任务执行完毕
    • 但不管wait参数为何值,整个程序都会等到所有任务执行完毕

      note:submit和map必须在shutdown之前

 

pool.submit()返回的对象是

concurrent.futures._base.Future类

add_done_callback(self,fn)
cancel(self)
cancelled(self)
done(self)
exception(self,timeout=None)
result(self,timeout=None)
running(self)
set_exception(self,exception)
set_result(self,result)
set_running_or_notify_cancel(self)
  • result(timeout=None) :取得结果,通过submit函数返回的任务句柄,使用result()方法可以获取任务的返回值,查看内部代码,发现这个方法是阻塞的
  • done()方法判断该任务是否结束
  • add_done_callback(fn) :回调函数

3、进程池和线程池

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

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

3.1 进程池

from concurrent.futures import ProcessPoolExecutor
import os
import time
def task(i):
    print(""+str(i)+"个在执行任务id:"+str(os.getpid()))
    time.sleep(1)
if __name__ == '__main__':
    start=time.time()

    pool = ProcessPoolExecutor(4) # 进程池里又4个进程

    for i in range(5): # 5个任务
        pool.submit(task,i)# 进程池里当前执行的任务i,池子里的4个进程一次一次执行任务
    pool.shutdown()
    print("耗时:",time.time()-start)

  python并发编程--进程&线程--其他模块-从菜鸟到老鸟(三)

 3.2 线程池

from concurrent.futures import ThreadPoolExecutor
from threading import currentThread

import time
def task(i):
    print(""+str(i)+"个在执行任务id:"+currentThread().name)
    time.sleep(1)
if __name__ == '__main__':
    start = time.time()

    pool = ThreadPoolExecutor(4) # 进程池里又4个线程
    for i in range(5): # 5个任务
        pool.submit(task,i)# 线程池里当前执行的任务i,池子里的4个线程一次一次执行任务
    pool.shutdown()
    print("耗时:",time.time()-start)

  python并发编程--进程&线程--其他模块-从菜鸟到老鸟(三)

  其他:done() 、 result()

  • 通过submit函数返回的任务句柄,能够使用done()方法判断该任务是否结束
  • 使用result()方法可以获取任务的返回值,查看内部代码,发现这个方法是阻塞的

 

 3.4列表+as_compelete模拟先进先出

    对于线程,这样可以模拟执行与结果的先进先出。

    但是对于进程会报错。

import time
from concurrent.futures import ProcessPoolExecutor,as_completed,ThreadPoolExecutor

def get_html(i):
    times=1
    time.sleep(times)
    print("第 NO.{i}  get page {times} finished".format(i=i,times=times))
    return "第 NO.{i} ".format(i=i)

start=time.time()
executor = ThreadPoolExecutor(max_workers=2)
# executor = ProcessPoolExecutor(max_workers=2) #进程池会导致后面的all_task报错

all_task = [executor.submit(get_html,(i)) for i in range(5)]


for future in as_completed(all_task):
    data = future.result()
    print("in main:get page {} success".format(data))
print('主进程结束--耗时',time.time()-start)

结果:

第 NO.0  get page 1 finished
第 NO.1  get page 1 finished
in main:get page 第 NO.0  success
in main:get page 第 NO.1  success
第 NO.2  get page 1 finished
in main:get page 第 NO.2  success
第 NO.3  get page 1 finished
in main:get page 第 NO.3  success
第 NO.4  get page 1 finished
in main:get page 第 NO.4  success
主进程结束--耗时 3.0034666061401367
结果:

相关文章:

  • 2021-11-27
  • 2021-11-01
  • 2021-11-20
  • 2021-11-25
  • 2021-11-17
  • 2021-06-09
  • 2021-09-17
  • 2022-12-23
猜你喜欢
  • 2021-06-30
  • 2021-07-12
  • 2021-07-16
  • 2022-02-07
  • 2021-10-05
  • 2021-09-28
  • 2021-07-26
相关资源
相似解决方案