python并发编程之进程池,线程池concurrent.futures

进程池与线程池

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

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

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

Python--concurrent.futures

1.concurent.future模块是用来创建并行的任务,提供了更高级别的接口,为了异步执行调用2.concurent.future这个模块用起来非常方便,它的接口也封装的非常简单3.concurent.future模块既可以实现进程池,也可以实现线程池4.模块导入进程池和线程池from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutorp = 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}

  

  

原文地址:https://www.cnblogs.com/xiao-apple36/p/9499000.html

时间: 2024-11-05 16:39:16

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

Java并发编程:进程和线程

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

并发编程之进程与线程

并发编程之进程与线程 2.1 线程与进程 2.1.1 进程 2.1.2 线程 2.1.3 二者对比 2.2 并行与并发 2.3 应用 2.1 线程与进程 2.1.1 进程 程序指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存.在指令运行过程中还需要用到磁盘.网络等设备.进程就是用来加载指令.管理内存.管理IO的. 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程. 进程就可以视为程序的一个实例.大部分程序可以同时运行多个实例进程(例如记

python并发编程之进程池,线程池

要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉只要你用并发,就会有锁的问题,但是你不能一直去自己加锁吧那么我们就用QUEUE,这样还解决了自动加锁的问题由Queue延伸出的一个点也非常重要的概念.以后写程序也会用到这个思想.就是生产者与消费者问题 一.Python标准模块--concurrent.futures(并发未来) concurent.future模块需要了解的1.concurent.fut

Python并发编程之进程2

引言 本篇介绍Python并发编程下的进程,先介绍进程的相关知识,然后对python中multiprocessing模块进行介绍(Process.Pipe.Queue以及 Lock). 进程(process) 在面向线程设计的系统(如当代多数操作系统.Linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器. 进程拥有自己独立的内存空间,所属线程可以访问进程的空间. 程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 例如,我们在PyCharm开发环境中写

Java并发编程——Executor接口及线程池的使用

在如今的程序里,单线程的程序,应该已经比较少了,而Java语言是内置支持多线程并发的,大家都说Java语言内置支持多线程,非常非常的强大和方便,但一直没有深入研究jdk内concurrent包.今天就认真学习了一下java.util.concurrent包,发现jdk多线程编程果然是强大和方便.本文是学习java.util.concurrent包内线程池及相关接口的一些总结. 任务接口抽象 Runnable接口 在java.lang包内,为多线程提供了Runnable接口. public int

Java并发编程、多线程、线程池…

Java多线程干货系列(1):Java多线程基础http://www.importnew.com/21136.html#comment-651146 40个Java多线程问题总结http://www.importnew.com/18459.html#comment-651217 Java线程面试题 Top 50http://www.importnew.com/12773.html Java并发编程:Thread类的使用http://www.cnblogs.com/dolphin0520/p/39

java高并发编程(五)线程池

摘自马士兵java并发编程 一.认识Executor.ExecutorService.Callable.Executors /** * 认识Executor */ package yxxy.c_026; import java.util.concurrent.Executor; public class T01_MyExecutor implements Executor { public static void main(String[] args) { new T01_MyExecutor(

【Java并发编程】21、线程池ThreadPoolExecutor源码解析

一.前言 JUC这部分还有线程池这一块没有分析,需要抓紧时间分析,下面开始ThreadPoolExecutor,其是线程池的基础,分析完了这个类会简化之后的分析,线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法.下面开始分析. 二.ThreadPoolExecutor数据结构 在ThreadPoolExecutor的内部,主要由BlockingQueue和AbstractQu

java并发编程(4)--线程池的使用

转载:http://www.cnblogs.com/dolphin0520/p/3932921.html 一. java中的ThreadPoolExecutor类 java.util.concurrent.ThreadPoolExecutor类时线程池中最核心的一个类,因此如果要透彻的了解java中线程池,必须先了解这个类.下面看ThreadPoolExecutor类的具体实现源码: 在ThreadPoolExecutor类中提供了四个构造方法: public class ThreadPoolE