进程池与线程池

在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多,

这会对服务端主机带来巨大的压力,甚至于不堪重负而瘫痪,于是我们必须对服务端开启的进程数或线程数加以控制,让机器在一个自己可以承受的范围内运行,这就是进程池或线程池的用途,

例如进程池,就是用来存放进程的池子,本质还是基于多进程,只不过是对开启进程的数目加上了限制

Python--concurrent.futures

1.concurent.future模块是用来创建并行的任务,提供了更高级别的接口,
为了异步执行调用
2.concurent.future这个模块用起来非常方便,它的接口也封装的非常简单
3.concurent.future模块既可以实现进程池,也可以实现线程池
4.模块导入进程池和线程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
p = ProcessPoolExecutor(max_works)对于进程池如果不写max_works:默认的是cpu的数目
p = ThreadPoolExecutor(max_works)对于线程池如果不写max_works:默认的是cpu的数目*5

基本方法

1、submit(fn, *args, **kwargs)
异步提交任务 2、map(func, *iterables, timeout=None, chunksize=1)
取代for循环submit的操作 3、shutdown(wait=True)
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前 4、result(timeout=None)
取得结果 5、add_done_callback(fn)
回调函数

 

进程池

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import currentThread
import os,time,random def task(n):
print("%s is running " % os.getpid())
time.sleep(random.randint(1,3))
return n*2 if __name__ == '__main__':
start = time.time()
executor = ProcessPoolExecutor(4) res = []
for i in range(10): # 开启10个任务
future = executor.submit(task,i) # 异步提交任务
res.append(future) executor.shutdown() # 等待所有进程执行完毕
print("++++>")
for r in res:
print(r.result()) # 打印结果 end = time.time()
print(end - start) ---------------------输出
2464 is running
9356 is running
10780 is running
9180 is running
2464 is running
10780 is running
9180 is running
9356 is running
10780 is running
9180 is running
++++>
0
2
4
6
8
10
12
14
16
18
6.643380165100098

线程池

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import currentThread
import os,time,random def task(n):
print("%s is running " % currentThread().getName())
time.sleep(random.randint(1,3))
return n*2 if __name__ == '__main__':
start = time.time()
executor = ThreadPoolExecutor(4) # 线程池 res = []
for i in range(10): # 开启10个任务
future = executor.submit(task,i) # 异步提交任务
res.append(future) executor.shutdown() # 等待所有线程执行完毕
print("++++>")
for r in res:
print(r.result()) # 打印结果 end = time.time()
print(end - start) ------------输出 <concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_0 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_1 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_2 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_3 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_3 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_1 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_0 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_2 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_3 is running
<concurrent.futures.thread.ThreadPoolExecutor object at 0x00000000025B0DA0>_1 is running
++++>
0
2
4
6
8
10
12
14
16
18
5.002286195755005

回调函数

import requests
import time
from concurrent.futures import ThreadPoolExecutor def get(url):
print('GET {}'.format(url))
response = requests.get(url)
time.sleep(2)
if response.status_code == 200: # 200代表状态:下载成功了
return {'url': url, 'content': response.text} def parse(res):
print('%s parse res is %s' % (res['url'], len(res['content'])))
return '%s parse res is %s' % (res['url'], len(res['content'])) def save(res):
print('save', res) def task(res):
res = res.result()
par_res = parse(res)
save(par_res) if __name__ == '__main__':
urls = [
'http://www.cnblogs.com/linhaifeng',
'https://www.python.org',
'https://www.openstack.org',
] pool = ThreadPoolExecutor(2)
for i in urls:
pool.submit(get, i).add_done_callback(task)#这里的回调函数拿到的是一个对象。得
# 先把返回的res得到一个结果。即在前面加上一个res.result() #谁好了谁去掉回调函数
# 回调函数也是一种编程思想。不仅开线程池用,开线程池也用
pool.shutdown() #相当于进程池里的close和join -------------输出
GET http://www.cnblogs.com/linhaifeng
GET https://www.python.org
http://www.cnblogs.com/linhaifeng parse res is 17426
save http://www.cnblogs.com/linhaifeng parse res is 17426
GET https://www.openstack.org
https://www.python.org parse res is 48809
save https://www.python.org parse res is 48809
https://www.openstack.org parse res is 60632
save https://www.openstack.org parse res is 60632

map

import requests
import time
from concurrent.futures import ThreadPoolExecutor def get(url):
print('GET {}'.format(url))
response = requests.get(url)
time.sleep(2)
if response.status_code == 200: # 200代表状态:下载成功了
return {'url': url, 'content_len': len(response.text)} if __name__ == '__main__':
urls = [
'http://www.cnblogs.com/linhaifeng',
'https://www.python.org',
'https://www.openstack.org',
] pool = ThreadPoolExecutor(2)
res = pool.map(get, urls) #map取代了for+submit pool.shutdown() # 相当于进程池里的close和join
print('=' * 30)
for r in res: # 返回的是一个迭代器
print(r) GET http://www.cnblogs.com/linhaifeng
GET https://www.python.org
GET https://www.openstack.org
{'url': 'http://www.cnblogs.com/linhaifeng', 'content_len': 17426}
{'url': 'https://www.python.org', 'content_len': 48809}
{'url': 'https://www.openstack.org', 'content_len': 60632}

  

自定义线程池  

from threading import Thread, currentThread
import time
import queue class MyThread(Thread): def __init__(self, queue):
super().__init__()
self.queue = queue
self.daemon = True # 子线程跟着主线程一起退出
self.start() def run(self):
"""
1、让他始终去运行,
2、去获取queue里面的任务,
3、然后给任务分配函数去执行(获取任务在执行)
:return:
"""
while True:
func, args, kwargs = self.queue.get() # 从队列中获取任务
func(*args, **kwargs)
self.queue.task_done() # 计数器 执行完这个任务后 (队列-1操作) class MyPool(object):
"""
在任务来到之前,提前创建好线程,等待任务
""" def __init__(self, num): # 线程数量
self.num = num
self.queue = queue.Queue()
for i in range(self.num):
MyThread(self.queue) def submit(self, func, args=(), kwargs={}):
self.queue.put((func, args, kwargs)) def join(self):
self.queue.join() # 等待队列里面的任务处理完毕 def task(i):
print(currentThread().getName(), i)
time.sleep(2) if __name__ == '__main__':
start = time.time()
pool = MyPool(3) # 实例化一个线程池
for i in range(4):
pool.submit(task, args=(i,))
pool.join()
print('运行的时间{}秒'.format(time.time() - start))

  

python并发编程之进程池,线程池concurrent.futures的更多相关文章

  1. python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...

  2. [Java并发编程(二)] 线程池 FixedThreadPool、CachedThreadPool、ForkJoinPool?为后台任务选择合适的 Java executors

    [Java并发编程(二)] 线程池 FixedThreadPool.CachedThreadPool.ForkJoinPool?为后台任务选择合适的 Java executors ... 摘要 Jav ...

  3. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  4. [Java并发编程(一)] 线程池 FixedThreadPool vs CachedThreadPool ...

    [Java并发编程(一)] 线程池 FixedThreadPool vs CachedThreadPool ... 摘要 介绍 Java 并发包里的几个主要 ExecutorService . 正文 ...

  5. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  6. Java并发编程系列-(6) Java线程池

    6. 线程池 6.1 基本概念 在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理.如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数 ...

  7. python并发编程之进程池,线程池,协程

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

  8. python并发编程之进程池、线程池、协程

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

  9. 并发编程系列:Java线程池的使用方式,核心运行原理、以及注意事项

    并发编程系列: 高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 线程池的缘由 java中为了提高并发度,可以使用多线程共同执行,但是如果有大量线程短时间之内被创建和销毁,会占用大量的 ...

随机推荐

  1. illustrator画梯形

    1.在空白文档上先绘制出一个长方形: 2.用鼠标点击工具箱中”自由变换“工具: 3.用鼠标指向长方形四个顶点中的任意一个,当鼠标的箭头变为相反反方向的双箭头时,再按住鼠标左键不要松手, 同时按住[sh ...

  2. python的6种基本数据类型--集合

    特征 1.确定性(元素必须可hash) 2.互异性(去重) 3.无序性(集合中的元素没有顺序,先后之分) >>> s = {1,1,1,2,2,3,4,5,6,7} # 创建 > ...

  3. java 块语句 和引用类型

    1.java中存在块语句,块语句分为四种 1.静态块 2.普通块 3.构造块 4.同步块 静态块的执行时机是在class文件装载的时候;静态块只会执行一次, 多个静态块的时候,按出现顺序执行,存放类的 ...

  4. 11-border(边框)

    边框 border:边框的意思,描述盒子的边框 边框有三个要素: 粗细 线性样式 颜色 border: solid 如果颜色不写,默认是黑色.如果粗细不写,不显示边框.如果只写线性样式,默认的有上下左 ...

  5. 延时、输入输出接口P0~P3

    1.寄存器 为了知道延时程序是如何工作的,我们必需首先了解延时程序中出现的一些符号,就从R1开始,R1被称之为工作寄存器.什么是工作寄存器呢?让我们从现实生活中来找找答案.如果出一道数学题:123+5 ...

  6. (数位dp)Bomb (hdu 3555)

    http://acm.hdu.edu.cn/showproblem.php?pid=3555     Problem Description The counter-terrorists found ...

  7. 如何更改linux文件的拥有者及用户组(chown和chgrp)

    http://blog.csdn.net/hudashi/article/details/7797393 一.基本知识   在Linux中,创建一个文件时,该文件的拥有者都是创建该文件的用户.该文件用 ...

  8. 20155326 2016-2017-2《Java程序设计》课程总结

    20155326 2016-2017-2<Java程序设计>课程总结 (按顺序)每周作业链接汇总 20155326刘美岑的第一次作业:第一次写博客,写下了对java的期待 20155326 ...

  9. js-倒计时原理

    <!DOCTYPE html><html>    <head>        <meta charset="UTF-8">      ...

  10. Maven的插件管理

    <pluginManagement> 这个元素和<dependencyManagement>相类似,它是用来进行插件管理的. 在我们项目开发的过程中,也会频繁的引入插件,所以解 ...