模块:ThreadPoolExecutor,ProcessPoolExecutor
导入方法:
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
原理:
    concurrent.futures是异步调用的机制
模块区分:
    from multiprocessing import Pool.apply/apply_async   既可同步也可异步
区分:
    进程池中进程的数量为计算机核数+1
    线程池中线程的数量为计算机核数*5
    进程池中的回调函数是父进程调用的,和子进程没有关系
    线程池中的回调函数是子线程调用的,和父进程没有关系
模块方法:
    shutdown()  等效于进程池Pool中的close和join的组合
使用方法:
    提交任务用submit
再强调:
    如果程序的IO操作比较多,则采用多线程的方式,因为多线程的切换速度比多进程快
    如果程序的计算比较多,则采用多进程的方式


小结:针对计算密集的程序来说,Pool或者ProcessPoolExecutor执行效率相当,而ThreadPoolExecutor相对于前两者效率更差
      所以当计算密集时使用多进程

#######线程池(进程池)(多任务提交)
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time

def func(num):
    sum = 0
    #求参数范围内的平方和
    for i in range(num):
        sum += i**2
    print(sum)

if __name__ == '__main__':
    #实例化线程池对象
    #tp=ProcessPoolExecutor(5)    #进程池只需改成ProcessPoolExecutor并且参数为操作系统核数+1即可
    tp=ThreadPoolExecutor(20)     #线程池中线程的数量为操作系统核数*5
    #计算程序执行到这里的时间,目的是为了能比较效率
    start = time.time()
    #准备开启1000个线程
    for i in range(1000):
        #提交给线程池开始执行线程的任务
        tp.submit(func,i)
    #以上的for循环可以用下列map函数代替
    #t.map(func,range(1000))    #map返回的结果是一个生成器对象
    tp.shutdown()   #主线程等待所有子线程执行完毕,相当于进程池中的close和join的组合
    #计算程序执行到这里的时间,并减去start,获得线程池中所有线程执行的时间效率
    print("线程池的消耗时间为{}".format(time.time() - start))


##########线程池的返回值
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time


def func(num):
    sum = 0
    for i in range(num):
        sum += i**2
    return sum


if __name__ == '__main__':
    t=ThreadPoolExecutor()
    res_l = []  #用于存放线程池中线程返回的结果
    for i in range(1000):
        re = t.submit(func,i)
        res_l.append(re)
    #t.shutdown() #此时不用到shutdown()原因是每个线程执行完都需要返回结果给re,所以每个线程在此约束条件下会完整的执行,而不会中途丢掉结果而去执行下一个任务
    #此时的程序依然是采用异步的机制,只不过因为需要获得返回每个线程的返回值所以才会出现类似同步的现象
    [print(i.result()) for i in res_l]
    #在Pool中获得结果是用get方法,而在ThreadPoolExecutor获得结果是用result方法
    #如果提交任务的方式采用的是map方法,则在获得结果时需要做一定的修改
    #res = t.map(func,range(1000))  返回的是一个生成器对象
    #t.shutdown()
    #res.__next__()  是获取单个结果,若需要获取多个结果采用for循环即可





########进程池中的回调函数(Pool也有回调函数)
from concurrent.futures import ProcessPoolExecutor
# 不管是ProcessPoolExecutor的进程池  还是Pool的进程池,回调函数都是父进程调用的。
import os
import requests

def func(num):
    sum = 0
    for i in range(num):
        sum += i ** 2
    return sum

def call_back_fun(res):
    # print(res.result(),os.getpid())
    print(os.getpid())

if __name__ == '__main__':
    print(os.getpid())
    t = ProcessPoolExecutor(20)
    for i in range(1000):
        t.submit(func,i).add_done_callback(call_back_fun)
    t.shutdown()
01-20 06:23