使用concurrent.futures模块中的线程池与进程池

线程池与进程池

以线程池举例,系统使用多线程方式运行时,会产生大量的线程创建与销毁,创建与销毁必定会带来一定的消耗,甚至导致系统资源的崩溃,这时使用线程池就是一个很好的解决方式。

“池”就说明了这里边维护了不止一个线程,线程池会提前创建好规定数量的线程,把需要使用多线程的任务提交给线程池,线程池会自己选择空闲的线程来执行提交的任务,任务完成后,线程并不会在池子中销毁,而是继续存在并等待完成下一个分配的任务。当线程池以满的时候,提交的线程会等待,也就是说线程池会有一个最大数量的运行线程限制。

进程池同样也是这个道理。

concurrent.futures模块为我们提供了ThreadPoolExecutor与ProcessPoolExecutor来使用线程进程池

ThreadPoolExecutor

下面是一个简单的例子

from concurrent.futures import ThreadPoolExecutor
import requests,time
url_list = ['https://www.cnblogs.com/', 'https://www.csdn.net/', 'https://github.com/']
def get_url(url):
content = requests.get(url).content.decode()
print(url+'已获取') pool = ThreadPoolExecutor(max_workers=3) start = time.time()
for url in url_list:
future = pool.submit(get_url,url)
# print(future)
end = time.time()
print(end-start)

输出的结果为:

0.0016434192657470703
https://www.cnblogs.com/已获取
https://www.csdn.net/已获取
https://github.com/已获取

例子中max_workers为指定线程个数,pool.submit为提交任务到线程执行,get_url为方法,url为参数

并且通过输出顺序可以看到线程池的执行并不会阻塞主线程的运行

print(future)被打了注释,现在我们取消注释运行一下:

Future at 0x7ff6cfaa8860 state=running
Future at 0x7ff6ce965860 state=running
Future at 0x7ff6ce96e278 state=running
0.006175518035888672
https://www.cnblogs.com/已获取
https://www.csdn.net/已获取
https://github.com/已获取

每提交一个任务后都会返回一个future对象,通过它可以查看任务运行的状态,state=running表示正在运行

future对象还有许多方法:

future.done()

from concurrent.futures import ThreadPoolExecutor
import requests,time
url_list = ['https://www.cnblogs.com/', 'https://www.csdn.net/', 'https://github.com/']
def get_url(url):
content = requests.get(url).content.decode()
print(url+'已获取') pool = ThreadPoolExecutor(max_workers=3)
future_list = []
start = time.time()
for url in url_list:
future = pool.submit(get_url,url)
print(future.done())
future_list.append(future)
end = time.time() print(end-start)
time.sleep(5)
for future in future_list:
print(future.done())

这里添加了future_list,为了显示效果中间添加sleep,最后结果为:

False
False
False
0.001546621322631836
https://www.cnblogs.com/已获取
https://www.csdn.net/已获取
https://github.com/已获取
True
True
True

future.done()可以显示当前允许状态

future.result()

from concurrent.futures import ThreadPoolExecutor
import requests,time
url_list = ['https://www.cnblogs.com/', 'https://www.csdn.net/', 'https://github.com/']
def get_url(url):
content = requests.get(url).content.decode()
print(url+'已获取')
return url pool = ThreadPoolExecutor(max_workers=3)
future_list = []
start = time.time()
for url in url_list:
future = pool.submit(get_url,url)
print(future.result())
future_list.append(future)
end = time.time() print(end-start)
for future in future_list:
print(future.result())

结果为:

https://www.cnblogs.com/已获取
https://www.cnblogs.com/
https://www.csdn.net/已获取
https://www.csdn.net/
https://github.com/已获取
https://github.com/
2.0975613594055176
https://www.cnblogs.com/
https://www.csdn.net/
https://github.com/

可见result()方法可以得到任务的返回值,但会阻塞,因为不运行完怎么会得到返回值呢?

除此之外还有很多方法:

使用map方法

from concurrent.futures import ThreadPoolExecutor
import requests,time
url_list = ['https://www.cnblogs.com/', 'https://www.csdn.net/', 'https://github.com/']
def get_url(url):
content = requests.get(url).content.decode()
print(url+'已获取')
return url pool = ThreadPoolExecutor(max_workers=3) pool.map(get_url,url_list)

与内建函数用法类似

使用wait方法

from concurrent.futures import ThreadPoolExecutor,wait
import requests,time
url_list = ['https://www.cnblogs.com/', 'https://www.csdn.net/', 'https://github.com/']
def get_url(url):
content = requests.get(url).content.decode()
print(url+'已获取')
return url pool = ThreadPoolExecutor(max_workers=3)
future_list = []
start = time.time()
for url in url_list:
future = pool.submit(get_url,url)
future_list.append(future) print(wait(future_list))
end = time.time()
print(end-start)

https://www.cnblogs.com/已获取
https://www.csdn.net/已获取
https://github.com/已获取
DoneAndNotDoneFutures(done={Future at 0x7f7506447da0 state=finished returned str, Future at 0x7f75074c9828 state=finished returned str, Future at 0x7f75064477f0 state=finished returned str}, not_done=set())

6.678021430969238

wait返回值是一个元组,元组里是已完成和未完成的两个集合,它的return_when参数接受3个选项FIRST_COMPLETED, FIRST_EXCEPTION 和ALL_COMPLETE,默认是ALL_COMPLETE,意味着所有都完成,FIRST_COMPLETED意味着有一个完成了就可以了, FIRST_EXCEPTION是第一个出现异常就会停止wait

例如:

from concurrent.futures import ThreadPoolExecutor,wait
import requests,time
url_list = ['https://www.cnblogs.com/', 'https://www.csdn.net/', 'https://github.com/']
def get_url(url):
content = requests.get(url).content.decode()
print(url+'已获取')
return url def error(url):
gg pool = ThreadPoolExecutor(max_workers=4)
future_list = []
start = time.time()
future_list.append(pool.submit(error,'https://www.cnblogs.com/'))
for url in url_list:
future = pool.submit(get_url,url)
future_list.append(future) print(wait(future_list,return_when='FIRST_EXCEPTION'))
end = time.time()
print(end-start)

DoneAndNotDoneFutures(done={Future at 0x7fd1a5b95320 state=finished raised NameError}, not_done={Future at 0x7fd1a4b11a90 state=running, Future at 0x7fd1a4b11a20 state=running, Future at 0x7fd1a4c897f0 state=running})
0.001996755599975586
https://www.cnblogs.com/已获取
https://www.csdn.net/已获取
https://github.com/已获取

ProcessPoolExecutor

进程池与线程池的使用方式基本相同,套用即可

使用concurrent.futures模块中的线程池与进程池的更多相关文章

  1. concurrent.futures模块(进程池&线程池)

    1.线程池的概念 由于python中的GIL导致每个进程一次只能运行一个线程,在I/O密集型的操作中可以开启多线程,但是在使用多线程处理任务时候,不是线程越多越好,因为在线程切换的时候,需要切换上下文 ...

  2. 线程与进程 concurrent.futures模块

    https://docs.python.org/3/library/concurrent.futures.html 17.4.1 Executor Objects class concurrent.f ...

  3. 线程池、进程池(concurrent.futures模块)和协程

    一.线程池 1.concurrent.futures模块 介绍 concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor:线程池,提供异步调用 Pro ...

  4. concurrent.futures模块(进程池/线程池)

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  5. Python并发编程之线程池/进程池--concurrent.futures模块

    一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/ ...

  6. python3 线程池-threadpool模块与concurrent.futures模块

    多种方法实现 python 线程池 一. 既然多线程可以缩短程序运行时间,那么,是不是线程数量越多越好呢? 显然,并不是,每一个线程的从生成到消亡也是需要时间和资源的,太多的线程会占用过多的系统资源( ...

  7. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...

  8. 使用concurrent.futures模块并发,实现进程池、线程池

    Python标准库为我们提供了threading和multiprocessing模块编写相应的异步多线程/多进程代码 从Python3.2开始,标准库为我们提供了concurrent.futures模 ...

  9. Python之路(第四十六篇)多种方法实现python线程池(threadpool模块\multiprocessing.dummy模块\concurrent.futures模块)

    一.线程池 很久(python2.6)之前python没有官方的线程池模块,只有第三方的threadpool模块, 之后再python2.6加入了multiprocessing.dummy 作为可以使 ...

随机推荐

  1. JQ-bootstrap我的开源前端框架

        因为实在不知道写啥,所以迟迟没有相关的介绍.但是必须要积累过程资产,所以还是介绍一下,不定哪天就有人用了.       首先还是介绍遇到的问题,我是做传统后台管理系统的,公司赶时髦,要用boo ...

  2. Perl的IO操作(1):文件句柄

    文件句柄 文件句柄用来对应要操作的文件系统中的文件,这么说不太严谨,但比较容易理解.首先为要打开的文件绑定文件句柄(称为打开文件句柄),然后在后续的操作中都通过文件句柄来操作对应的文件,最后关闭文件句 ...

  3. 《C#并发编程经典实例》学习笔记—异步编程关键字 Async和Await

    C# 5.0 推出async和await,最早是.NET Framework 4.5引入,可以在Visual Studio 2012使用.在此之前的异步编程实现难度较高,async使异步编程的实现变得 ...

  4. JS实现分钟数和时间小时 格式的转换

    1.分钟数转换为 小时:分钟  function ChangeHourMinutestr(str) { if (str !== "0" && str !== &qu ...

  5. redis实现高并发下的抢购/秒杀功能

    之前写过一篇文章,高并发的解决思路(点此进入查看),今天再次抽空整理下实际场景中的具体代码逻辑实现吧:抢购/秒杀是如今很常见的一个应用场景,那么高并发竞争下如何解决超抢(或超卖库存不足为负数的问题)呢 ...

  6. What does operator “dot” (.) mean?

    Question: Given the code : A = [1 2 3; 3 2 1] B = A.^2 The output : B = 1 4 9 9 4 1 But if I do this ...

  7. [转] 快速部署Tomcat项目的Shell脚本

    为了做集群测试,在每台机器上装了3个tomcat,每次发布项目的时候都要反复敲一些命令,重启tomcat之前先检查tomcat进程有没有停掉,没有还要手动kill该进程. 发布次数多了,操作就比较繁琐 ...

  8. MyBatis中映射器Mapper概述

    MyBatis真正强大之处在于它的映射器.因为它异常强大并且编写相对简单,不仅比传统编写SQL语句做的更好并且能节省将近95%的代码量 XML中顶级元素汇总 cache: 给定命名空间的缓存配置 ca ...

  9. Java岗 面试考点精讲(基础篇01期)

    即将到来金三银四人才招聘的高峰期,渴望跳槽的朋友肯定跟我一样四处找以往的面试题,但又感觉找的又不完整,在这里我将把我所见到的题目做一总结,并尽力将答案术语化.标准化.预祝大家面试顺利. 术语会让你的面 ...

  10. Python 部分系统类的常用方法整理

    下面是常用的几个系统类的常用方法整理: list: 列表[1, 2,...] set: 集合,无重复元素{1, 2,...} str: 字符串 dict: 字典{a:'a', b:'b',...} T ...