Python自带的线程池和进程池一文我们都知道,无论是Java、C++、Go还是Python,都有线程的概念。但是我们知道线程是不能随便创建的。就像每一个员工被招进来一样,都是有代价的。无限招募最后肯定会导致各种崩溃。所以一般情况下,我们都会引入线程池的概念。其实质就是我只是招了几个正式员工,给他们分配了工作。某人的工作做完后,我去任务中心接新的工作。防止任务太多,一次招太多工人,最后系统崩溃。HappyMomentIdealmulti-threadingActualmulti-threadingfromconcurrent.futuresimport...可能是线程池用的越来越多吧。从Python3.2+开始,它成为了一个内置模块。是的,可以直接使用,不需要pip安装。concurrent.futures下主要有两个接口。ThreadPoolExecutor线程池。ProcessPoolExecutor进程池。这里没有所谓的异步池。个人看法:虽然异步性能很高,但是除了Go,其他实现目前都不是很好,用法有点怪异。当然,你可以批评我,我承认。线程池示例代码importtimefromconcurrent.futuresimportThreadPoolExecutorimportrandom#max_workers表示worker数量,即线程池中的线程数pool=ThreadPoolExecutor(max_workers=10)#tasklisttask_list=["任务1","任务2","Task3","Task4",]defhandler(task_name):#randomsleep,模仿任务执行时间的不确定性n=random.randrange(5)time.sleep(n)print(f"taskcontent:{task_name}")if__name__=='__main__':#遍历任务,fortaskintask_list:"""交给函数处理,submit会把所有任务提交到一个地方,不会阻塞然后线程池中的每个线程都会来取任务,如:线程池有3个线程,但是有5个任务会先拿走3个任务,每个线程处理完自己的任务后再处理其中一个线程,然后来到提交任务区再拿走另一个任务“””池。submit(handler,task)print("mainexecutioncompleted")执行结果发现的问题其实是并发的,不要怀疑,但是你有没有发现问题,main先执行了,什么意思?这意味着我运行main完成后,它并不关心子线程的死活。能不能设置成子线程全部执行完后才执行主函数?当然,只需要一个参数。pool.shutdown()要完成上面的问题,我们需要一个参数,加入这个参数之后。可以让主线程等所有的子线程都执行完了再主线程执行完。示例代码...if__name__=='__main__':#遍历任务,fortaskintask_list:"""交给函数处理,submit会将所有任务提交到一个地方然后线程池中的每个线程都会来取任务,如:线程池中有3个线程,但是如果有5个任务,则先拿走三个任务,每个线程处理完自己的任务后,再处理其中一个线程,然后来到提交的任务区再拿一个task"""pool.submit(handler,task)pool.shutdown()print("mainexecutioncompleted")主要是第13行的pool.shutdown()执行结果这次的结果就是我们想要的,hhh!!!add_done_callbackadd_done_callback可以理解为回调函数,线程执行完毕后,会自动调用指定的回调函数。并且可以获得线程执行函数的返回值。有什么用,我没用过,怪我无知。示例代码importtimefromconcurrent.futuresimportThreadPoolExecutorimportrandomfromconcurrent.futures._baseimportFuture#max_workers表示worker数量,即线程池中的线程数pool=ThreadPoolExecutor(max_workers=10)#tasklisttask_list=["任务1","任务2","任务3","任务4",]defhandler(task_name):#randomsleep,模仿任务执行时间的不确定性n=random.randrange(5)time.sleep(n)print(f"任务内容:{task_name}")returnf"任务内容:{task_name}"defdone(res:Future):print("done获得的返回值:",res.result())if__name__=='__main__':#遍历任务,fortaskintask_list:future=pool.submit(handler,task)#type:Futurefuture.add_done_callback(done)pool.shutdown()print("mainexecutioncompleted")注意:代码的第17、27、28行!我觉得executioneffect可能一般会用在一些Aftermath的作品中。多进程模式其实通过上面的几个例子,我们基本知道了上面线程池的使用方法。但是我们都知道,由于GIL(GlobalInterpreterLock)的存在,Python线程不能并发分布到多个物理核上。所以是IO密集型的,像爬虫,读写文件,用线程池就可以了。但是如果你说我是野蛮人,顶梁柱,我坚持用Python做计算应用,比如图片压缩,视频流,那也没办法,需要用多进程池的方式。其实通过并发接口,你可以很方便的创建一个进程池,只需要修改两个地方。...#改为导入进程池方法fromconcurrent.futuresimportProcessPoolExecutor...if__name__=='__main__':...#进程池方法pool=ProcessPoolExecutor(max_workers=10)...修改这两个地方即可,其他完全一样同上。小结本文主要讲Python自带的线程池和进程池。比较有特色的是ThreadPoolExecutor和ProcessPoolExecutor的接口是一样的。您只需要修改导入的包即可。并发接口主要有pool.submit()、pool.shutdown()、future.add_done_callback()。基本上,这些足够你自己使用了。本文转载自微信公众号《Python爬虫与数据挖掘》,可通过以下二维码关注。转载本文请联系Python爬虫与数据挖掘公众号。
