1. 池

池分为:进程池、线程池

池:预先的开启固定个数的进程数/线程数,当任务来临的时候,直接提交给已经开好的进程 / 线程,让这个进程 / 线程去执行就可以了。

池节省了进程、线程的开启、关闭、切换需要的时间,并且减轻了操作系统调度的负担。

concurrent.futures模块中:ProcessPoolExcutor类(进程池)、ThreadPoolExcutor类(线程池)

1.1 进程池

进程池缺点:

  • 开销大
  • 一个池中的任务个数限制了我们程序的并发个数
# 没有参数和返回值
import os
import time
import random
from concurrent.futures import ProcessPoolExecutor
# submit + shutdown
def func():
print('start',os.getpid())
time.sleep(random.randint(1,3))
print('end', os.getpid())
if __name__ == '__main__':
p = ProcessPoolExecutor(5)
for i in range(10):
p.submit(func)
p.shutdown() # 关闭池之后就不能继续提交任务,并且会阻塞,直到已经提交的任务完成
print('main',os.getpid())
# 任务的参数 + 返回值
def func(i,name):
print('start',os.getpid())
time.sleep(random.randint(1,3))
print('end', os.getpid())
return '%s * %s'%(i,os.getpid())
if __name__ == '__main__':
p = ProcessPoolExecutor(5)
ret_l = []
for i in range(10):
ret = p.submit(func,i,'alex')
ret_l.append(ret)
for ret in ret_l:
print('ret-->',ret.result()) # ret.result() 同步阻塞
print('main',os.getpid())

1.2 线程池

# 示例
from concurrent.futures import ThreadPoolExecutor
def func(i):
print('start', os.getpid())
time.sleep(random.randint(1,3))
print('end', os.getpid())
return '%s * %s'%(i,os.getpid())
tp = ThreadPoolExecutor(20) # 方法一:
ret = tp.map(func,range(20)) # a
for i in ret: # b
print(i) # c # a,b,c三行 相当于 下面1,2,3,4,5,6六行 # 方法二:
# ret_l = [] # 1
# for i in range(20): # 2
# ret = tp.submit(func,i) # 3
# ret_l.append(ret) # 4
tp.shutdown()
print('main')
# for ret in ret_l: # 5
# print(ret.result()) # 6

1..3 回调函数

对象.add_done_callback(子线程执行完毕之后要执行的代码对应的函数名)

效率高

执行完子线程任务之后直接调用对应的回调函数

爬取网页:需要等待数据传输和网络上的响应高IO操作的 — 交子线程完成

分析网页:没有什么IO操作 — 这个操作没必要在子线程完成,交给回调函数完成

add_done_callback
# 示例:爬虫
import requests
from concurrent.futures import ThreadPoolExecutor
def get_page(url):
res = requests.get(url)
return {'url':url,'content':res.text} def parserpage(ret):
dic = ret.result()
print(dic['url'])
tp = ThreadPoolExecutor(5)
url_lst = [
'http://www.baidu.com',
'http://www.cnblogs.com',
'http://www.douban.com',
'http://www.tencent.com',
'http://www.xinhuanet.com/',
'https://www.toutiao.com/',
]
ret_l = []
for url in url_lst:
ret = tp.submit(get_page,url)
ret_l.append(ret)
ret.add_done_callback(parserpage)

1.4 总结

ThreadPoolExcutor类
ProcessPoolExcutor类 创建一个池子
tp = ThreadPoolExcutor(池中线程(CPU个数*5)/进程(CPU个数)的个数)
异步提交任务
ret = tp.submit(需要在子线程执行的函数名,参数1,参数2....)
获取返回值
ret.result() 是一个阻塞方法
在异步的执行完所有任务之后,主线程/主进程才开始执行的代码
tp.shutdown() 阻塞 直到所有的任务都执行完毕
map方法
ret = tp.map(需要在子线程执行的函数名(如:func),iterable) 迭代获取iterable中的内容,作为func的参数,让子线程来执行对应的任务
for i in ret: 每一个都是任务的返回值
绑定回调函数
ret.add_done_callback(子线程执行完毕之后要执行的代码对应的函数名)
要在ret对应的任务执行完毕之后,直接继续执行add_done_callback绑定的函数中的内容,并且ret的结果会作为参数返回给绑定的函数

1.做一些操作时是单独开启线程、进程还是池?

  • 1.如果只是开启一个子线程做一件事情,就可以单独开线程
  • 2.有大量的任务等待程序去做,要达到一定的并发数,就开启线程池
  • 3.根据你程序的io操作也可以判定是用池还是不用池?
    • socket的server端:大量的阻塞io —recv、recvfrom、socketserver —— 不用池。
    • 爬虫的时候 —— 用池

2.进程 和 线程都有锁:

  • 所有在线程中能工作的基本都不能在进程中工作
  • 在进程中能够使用的基本在线程中也可以使用

python — 池的更多相关文章

  1. python进程池与线程池

    为什么会进行池化? 一切都是为了效率,每次开启进程都会分配一个属于这个进程独立的内存空间,开启进程过多会占用大量内存,系统调度也会很慢,我们不能无限的开启进程. 进程池原来大概如下图 假设有100个任 ...

  2. python进程池:multiprocessing.pool

    本文转至http://www.cnblogs.com/kaituorensheng/p/4465768.html,在其基础上进行了一些小小改动. 在利用Python进行系统管理的时候,特别是同时操作多 ...

  3. Python爬虫代理池

    爬虫代理IP池 在公司做分布式深网爬虫,搭建了一套稳定的代理池服务,为上千个爬虫提供有效的代理,保证各个爬虫拿到的都是对应网站有效的代理IP,从而保证爬虫快速稳定的运行,当然在公司做的东西不能开源出来 ...

  4. python线程池实现

    python 的线程池主要有threadpool,不过它并不是内置的库,每次使用都需要安装,而且使用起来也不是那么好用,所以自己写了一个线程池实现,每次需要使用直接import即可.其中还可以根据传入 ...

  5. python——有一种线程池叫做自己写的线程池

    这周的作业是写一个线程池,python的线程一直被称为鸡肋,所以它也没有亲生的线程池,但是竟然被我发现了野生的线程池,简直不能更幸运~~~于是,我开始啃源码,实在是虐心,在啃源码的过程中,我简略的了解 ...

  6. 《转》python线程池

    线程池的概念是什么? 在IBM文档库中这样的一段描写:“在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是 如此,虚拟机将试图跟踪每一个对象 ...

  7. 一个简单的python线程池框架

    初学python,实现了一个简单的线程池框架,线程池中除Wokers(工作线程)外,还单独创建了一个日志线程,用于日志的输出.线程间采用Queue方式进行通信. 代码如下:(不足之处,还请高手指正) ...

  8. 一个python线程池的源码解析

    python为了方便人们编程高度封装了很多东西,比如进程里的进程池,大大方便了人们编程的效率,但是默认却没有线程池,本人前段时间整理出一个线程池,并进行了简单的解析和注释,本人水平有限,如有错误希望高 ...

  9. Python之路【第八篇】python实现线程池

    线程池概念 什么是线程池?诸如web服务器.数据库服务器.文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务.构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就 ...

随机推荐

  1. shell 字符串分割cut

    cut 选项与参数 -d:后面接分隔字符.与-f一起使用. -f:依据-d的分隔字符将一段信息分隔数段,用-f取出第几段的意思. -c:以字符的单位取出固定字符区间 [zhang@localhost ...

  2. reGeorg(不需要外网ip的代理)

    reGeorg _____ ______ __|___ |__ ______ _____ _____ ______ | | | ___|| ___| || ___|/ \| | | ___| | \ ...

  3. 异步机制 - IO完成端口

    1 KQUEUE KeInitializeQueue VOID KeInitializeQueue( IN PKQUEUE  Queue, IN ULONG  Count  OPTIONAL ); l ...

  4. Leetcode题目322.零钱兑换(动态规划-中等)

    题目描述: 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: c ...

  5. CISCO实验记录六:EIGRP路由协议

    一.要求 1.查看当前路由协议 2.清空路由设置 3.使用EIGRP协议创建路由 4.查看EIGRP的邻居表 5.关闭自动汇总 6.使用手工汇总 二.实现 1.查看当前路由协议 #show ip pr ...

  6. 安装VMware虚拟机和centos操作系统

    1,安装包:百度网盘: 2,安装教程:https://blog.csdn.net/qq_31362105/article/details/80706096  配置好操作系统,内存,网络等: 3,Cen ...

  7. 求N个集合的并集

    做容器放置实验时,需要计算下载N个Images的总size(Image之间可能会有可以共享的size). 一开始想到的是Images两两之间求交集,然后慢慢推到了容斥原理...时间复杂度大概就是O(N ...

  8. python 调用github的api,呈现python的受欢迎的程度

    1 使用api调用数据: 在浏览器的地址栏中输入: https://api.github.com/search/repositories?q=language:python&sort=star ...

  9. vue开发(一)安装

    1.安装nodejshttps://nodejs.org/zh-cn/ 2.vs2019  工具-获取工具和功能 勾选nodejs开发并安装 3.新建基于vuejs web应用程序 4.右键项目在此处 ...

  10. OOM异常的发生原因

    一,jvm内存区域 1,程序计数器 一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. 2,java栈 与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存 ...