Python基础10.3:并发编程-----进程/线程池

线程/进程池

concurrent.futures模块 线程池,进程池都能够用相似的方式开启\使用

  实例化 创建池
  向池中提交任务,submit 传参数(按照位置传,按照关键字传)

import time
import random
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor

def func1(name,age):
    print(current_thread().ident,'开始')
    print(name,age)
    time.sleep(random.randint(1,4))
    print(current_thread().ident,'结束')

tp = ThreadPoolExecutor(4)
for i in range(10):
    tp.submit(func1,'alex',18)
线程池
import time
import random
import os
from concurrent.futures import ProcessPoolExecutor

def func1(name,age):
    print(os.getpid(),'开始')
    print(name,age)
    time.sleep(random.randint(1,4))
    print(os.getpid(),'结束')

if __name__ == '__main__':
    tp = ProcessPoolExecutor(4)
    for i in range(10):
        tp.submit(func1,'alex',18)
进程池
什么是池:
      # 要在程序开始的时候,还没提交任务先创建几个线程或者进程 放在一个池子里,这就是池
池的优点:
  # 如果先开好进程/线程,那么有任务之后就可以直接使用这个池中的数据了
  # 并且开好的线程或者进程会一直存在在池中,可以被多个任务反复利用
    # 这样极大的减少了开启\关闭\调度线程/进程的时间开销
  # 池中的线程/进程个数控制了操作系统需要调度的任务个数,控制池中的单位
    # 有利于提高操作系统的效率,减轻操作系统的负担        
#1 介绍
concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用
ProcessPoolExecutor: 进程池,提供异步调用
Both implement the same interface, which is defined by the abstract Executor class.

#2 基本方法
#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)
回调函数

# done()
判断某一个线程是否完成

# cancle()
取消某个任务

获取池的返回结果

import os
import time,random
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def func(a,b):
    print(os.getpid(),'start',a,b)
    time.sleep(random.randint(1,4))
    print(os.getpid(),'end')
    return a*b

if __name__ == '__main__':
    tp = ProcessPoolExecutor(4)
    futrue_l = {}
    for i in range(20):         # 异步非阻塞的
        ret = tp.submit(func,i,b=i+1)
        futrue_l[i] = ret
        # print(ret.result())   # Future未来对象
    for key in futrue_l:       # 同步阻塞的
        print(key,futrue_l[key].result())
获取任务结果

map  只适合传递简单的参数,并且必须是一个可迭代的类型作为参数

import os
import time,random
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def func(a):
    print(os.getpid(),'start',a[0],a[1])
    time.sleep(random.randint(1,4))
    print(os.getpid(),'end')
    return a[0]*a[1]

if __name__ == '__main__':
    tp = ProcessPoolExecutor(4)
    ret = tp.map(func,((i,i+1) for i in range(20)))
    for key in ret:       # 同步阻塞的
        print(key)
使用map传递参数

回调函数 : 效率最高的

import time,random
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor

def func(a,b):
    print(current_thread().ident,'start',a,b)
    time.sleep(random.randint(1,4))
    print(current_thread().ident,'end',a)
    return (a,a*b)

def print_func(ret):       # 异步阻塞
    print(ret.result())

if __name__ == '__main__':
    tp = ThreadPoolExecutor(4)
    futrue_l = {}
    for i in range(20):         # 异步非阻塞的
        ret = tp.submit(func,i,b=i+1)
        ret.add_done_callback(print_func)  # ret这个任务会在执行完毕的瞬间立即触发print_func函数,并且把任务的返回值对象传递到print_func做参数
        # 异步阻塞 回调函数 给ret对象绑定一个回调函数,等待ret对应的任务有了结果之后立即调用print_func这个函数
        # 就可以对结果立即进行处理,而不用按照顺序接收结果处理结果
回调函数示例
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import requests
import os

def get_page(url):    # 访问网页,获取网页源代码   线程池中的线程来操作
    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):   # 获取到字典结果之后,计算网页源码的长度,把https://www.baidu.com : 1929749729写到文件里   线程任务执行完毕之后绑定回调函数
    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/'
    ]
    td = ThreadPoolExecutor(4)
    for i in urls:
        ret = td.submit(get_page,i)
        ret.add_done_callback(parse_page)
回调函数示例2

 

posted @ 2019-06-18 23:14  CatdeXin  阅读(172)  评论(0编辑  收藏  举报