铁乐学python_Day42_线程池

concurrent.futures 异步调用模块

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

基本方法

submit(fn, *args, **kwargs)
异步提交任务 map(func, *iterables, timeout=None, chunksize=1)
取代for循环submit的操作 shutdown(wait=True)
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前 result(timeout=None)
取得结果 add_done_callback(fn)
回调函数 例: 进程池-异步调用
from concurrent.futures import ProcessPoolExecutor
import os, time, random def task(n):
print('%s is runing' % os.getpid())
time.sleep(random.randint(1, 3))
return n ** 2 if __name__ == '__main__':
# 创建异步调用的进程池,最大工作进程为3
executor = ProcessPoolExecutor(max_workers=3)
futures = []
for i in range(11):
# submit提交任务
future = executor.submit(task, i)
futures.append(future)
# 关闭进程池及等待池内所有任务执行完毕后回收资源
executor.shutdown(True)
print('+++>')
for future in futures:
# result取得函数结果
print(future.result()) 运行效果如下:
8984 is runing
8260 is runing
8772 is runing
8984 is runing
8772 is runing
8984 is runing
8260 is runing
8772 is runing
8772 is runing
8984 is runing
8772 is runing
+++>
0
1
4
9
16
25
36
49
64
81
100 例:线程池-异步调用-回调函数
import time
from concurrent.futures import ThreadPoolExecutor def func(i):
print(i*'*')
time.sleep(1)
return i def callb(arg):
print(arg.result() ** 2) if __name__ == '__main__':
thread_pool = ThreadPoolExecutor(5)
for i in range(1, 11):
# 回调函数,使用前面任务的函数结果做为传参到callb函数中异步执行
ret = thread_pool.submit(func, i).add_done_callback(callb)
thread_pool.shutdown() 运行效果如下:(这里并没有建列表,回调函数显示的结果是无序的)
*
**
***
****
*****
1
******
16
*******
9
********
25
*********
4
**********
36
49
81
64
100 例:线程池中map的用法(生成器)
from concurrent.futures import ThreadPoolExecutor
import time, random def task(n):
print(n * '*')
time.sleep(random.randint(1, 3))
return n ** 2 if __name__ == '__main__':
executor = ThreadPoolExecutor(max_workers=3)
# for i in range(1,11):
# executor.submit(task,i)
ret = executor.map(task, range(1, 11))
# executor.map(task, range(1, 11))一行取代了上面注释掉的for+submit两行,
# 且这个时候只是运行了task函数,task函数return的结果并没有拿到,
# 如果要拿到它的结果,可以赋个变量名给它,它是一个生成器,for循环next取值显示就可以了。
for i in range(10):
print(next(ret)) 运行效果如下:
*
**
***
****
1
*****
4
******
*******
********
9
*********
16
25
36
**********
49
64
81
100 例:回调函数
from concurrent.futures import ProcessPoolExecutor
import requests
import os def get_page(url):
'''
get url请求是200被正常响应时的结果
:param url:
:return:
'''
print('<进程%s> get %s' % (os.getpid(), url))
respone = requests.get(url)
if respone.status_code == 200:
return {'url': url, 'text': respone.text} def parse_page(res):
'''
将get_page函数的return结果url的值写入db文件中
:param res:
:return:
'''
res = res.result()
print('<进程%s> parse %s' % (os.getpid(), res['url']))
parse_res = 'url:<%s> size:[%s]\n' % (res['url'], len(res['text']))
with open('db.txt', 'a') as f:
f.write(parse_res) if __name__ == '__main__':
urls = [
'https://www.baidu.com',
'https://www.python.org',
'https://www.openstack.org',
'https://help.github.com/',
'http://www.sina.com.cn/'
] p = ProcessPoolExecutor(3)
for url in urls:
# 将前者get_page的return结果做为参数传入parse_page当中
# add 加,done 完成,callback 回调
p.submit(get_page, url).add_done_callback(parse_page)
# parse_page拿到的是一个future对象obj,需要用obj.result()拿到结果 运行效果如下:
<进程7264> get https://www.baidu.com
<进程8228> get https://www.python.org
<进程8988> get https://www.openstack.org
<进程7264> get https://help.github.com/
<进程3244> parse https://www.baidu.com
<进程7264> get http://www.sina.com.cn/
<进程3244> parse https://help.github.com/
<进程3244> parse http://www.sina.com.cn/
<进程3244> parse https://www.openstack.org
<进程3244> parse https://www.python.org db.txt里内容:
url:<https://www.baidu.com> size:[2443]
url:<https://help.github.com/> size:[128491]
url:<http://www.sina.com.cn/> size:[584087]
url:<https://www.openstack.org> size:[63796]
url:<https://www.python.org> size:[48744]

浅析进程和线程的使用场景

  • 当内存不需要共享,且高计算的时候,用进程;
  • 当内存需要共享,且高IO的时候,用线程。
  • 当并发很大的时候
    • 多进程 : 多个任务 —— 进程池 :(数量)cpu个数、cpu个数+1
    • 多线程 :多个任务 —— 线程池 :(数量)cpu个数*5
    • 4CPU : 开5个进程 —— 每进程再开20条线程:可完成100个任务
    • 例:50000并发: 5进程20线程500协程

end

参考:http://www.cnblogs.com/Eva-J/articles/8306047.html

铁乐学python_Day42_线程池的更多相关文章

  1. 铁乐学python_Day42_线程-信号量事件条件

    铁乐学python_Day42_线程-信号量事件条件 线程中的信号量 同进程的一样,Semaphore管理一个内置的计数器, 每当调用acquire()时内置计数器-1:调用release() 时内置 ...

  2. 铁乐学python_Day42_锁和队列

    铁乐学python_Day42_锁和队列 例:多个线程抢占资源的情况 from threading import Thread import time def work(): global n tem ...

  3. 铁乐学python_Day41_线程01

    线程概念的引入背景 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程. 程序和进程的区别就在于: 程序是 ...

  4. 铁乐学python_Day40_进程池

    进程之间的数据共享 基于消息传递的并发编程是大势所趋, 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合,通过消息队列交换数据. 这样极大地减少了对使用锁和其他同步手段的需求,还可以扩展到分 ...

  5. 铁乐学python_Day44_IO多路复用

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO ...

  6. 铁乐学python_Day39_多进程和multiprocess模块2

    铁乐学python_Day39_多进程和multiprocess模块2 锁 -- multiprocess.Lock (进程同步) 之前我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发 ...

  7. 铁乐学python_Day43_协程

    铁乐学python_Day43_协程 引子 之前我们学习了线程.进程的概念,了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道理来说我们已经算是把cpu的利用率提高很多了. ...

  8. 铁乐学python_Day38_多进程和multiprocess模块1

    铁乐学python_Day38_多进程和multiprocess模块1 [进程] 运行中的程序就是一个进程. 所有的进程都是通过它的父进程来创建的. 因此,运行起来的python程序也是一个进程,那么 ...

  9. 铁乐学python_day01-和python有关的唠嗑

    铁乐学python_day01-和python有关的唠嗑 文:铁乐与猫 2018-03-16 01_python的历史 python的创始人为荷兰人吉多·范罗苏姆(Guido van Rossum). ...

随机推荐

  1. jenkins自动化部署

    目录 typora-copy-images-to: pic Jenkins部署文档 一.安装环境 1.CentOs下安装JDK 2.CentOS安装Maven 3.CentOS安装git 4.Cent ...

  2. Android自动化压力测试图解教程——Monkey工具 (转)

    有时候我们需要对一个软件进行压力测试,检查该软件的性能.如果是人工进行测试的话,效率会低很多,而且会比较枯燥.这时,Android中的一个命令行工具Monkey就可以为我们减轻很多重复而又繁琐的工作. ...

  3. unity之定制脚本模板

    1.unity的脚本模板        新版本unity中的C#脚本有三类,第一类是我们平时开发用的C# Script:第二类是Testing,用来做单元测试:第三类是Playables,用作Time ...

  4. [原] Bash Script 显示其自身位置

    SOURCE="${BASH_SOURCE[0]}" BIN_DIR="$( dirname "$SOURCE" )" while [ -h ...

  5. 基础拾遗----RabbitMQ

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  6. Eclipse的版本命名

    Eclipse自3.1开始使用木星的卫星作为版本名,例如: 木卫一:伊奥 lo木卫二:欧罗巴 Europa木卫三:伽倪墨得斯 Ganymede木卫四:卡利斯托 Callisto .... Eclips ...

  7. java并发编程的艺术(三)---lock源码

    本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...

  8. 小tip: base64:URL背景图片与web页面性能优化——张鑫旭

    一.base64百科 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,可用于在HTTP环境下传递较长的标识信息. 某人: 唉,我彻底废柴了,为何上面明明是中文,洒家却看不懂嘞,为什 ...

  9. 了解JS

    什么是js? JS,是JavaScript的缩写形式,JavaScript是一种基于对象和事件驱动并且具有相对 安全性的客户端脚本语言. 借用java之名,但和java没有关系 javascript历 ...

  10. 关于java.lang.NoClassDefFoundError: org/apache/commons/collections/FastHashMap的错误解决办法

    在JavaEE开发中,在把配置文件中的数据或用户表单提交上来的数据,封装在相应JavaBean的对象的对应属性中时:在实际开发中,使用第三方法工具包BeanUtils(commons-beanutil ...