Python线程池

一次运行一个任务:

from concurrent.futures import ThreadPoolExecutor


def foo(a, b):
    print(a)
    print(b)


# executor = ThreadPoolExecutor(max_workers=1)
# executor.submit(foo)
# executor.shutdown()
with ThreadPoolExecutor(max_workers=1) as executor:
    executor.submit(foo, 'foo', 'bar')

这里用了with语句,当然你也可以选择不用with,就是注释掉的代码,你需要手动关闭线程池.

这里说一下with语句,很多人都不了解其细节.

在进入with语句块的时候,会执行__entry__()函数,然后这个函数的返回值给as后面的那个变量, 当退出with语句块的时候,会执行__exit__()函数.

来看一下源代码:

def __enter__(self):
    return self

def __exit__(self, exc_type, exc_val, exc_tb):
    self.shutdown(wait=True)
    return False

当你自己的class定义了__enter__和__exit__后,也就可以安心的使用with语句了.

一般来说,__enter__都是return self,而__exit__都是结束的时候你要做的事情.

用with语句的一个好处是,你不需要精力放在线程池的建立和关闭上, 你只需要关注你想要实现什么.

就像你写web,你不许要考虑con tent-type,这不应该是程序员应该考虑的,程序员更多的把精力放在业务上.

如果你想一次执行多个任务怎么办?

使用map函数.

import os
from concurrent.futures import ThreadPoolExecutor


def foo(a, b):
    print(a)
    print(b)


with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
    executor.map(foo, (1, 2, 3), (3, 2, 3))

map函数的定义如下:

def map(self, fn, *_iterables, timeout=None, chunksize=1):

第一个参数是接受一个函数(函数名字,不要加后面的括号),第二个参数是一个可变参数,它需要一个多个迭代器.

因为,你的那个要执行任务的函数可能需要多个参数,那么迭代器的数量与参数的数量是一样的.

过去的时候,我不知道可以接受多个迭代器,所以用的模式匹配……

import os
from concurrent.futures import ThreadPoolExecutor


def foo(data):
    a, b = data
    print(a)
    print(b)


iter1 = (1, 2, 3)
iter2 = (3, 2, 3)
with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
    executor.map(foo, zip(iter1, iter2))

看上去好蠢.


注意看这行的代码: with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor

max_workers=os.cpu_count(),这样做有什么好处呢?你的代码是可计算的,什么意思,你的电脑CPU是4核心,他的电脑是8核心CPU, 那么你的程序移植到他的电脑上去后,可以发挥最佳效果.


额外说点东西, 为什么 with语句会与__entry__和__exit__这两个函数有联系,这个叫协议.

举个例子, a == b 等价于 a.__eq__(b), 如果你是Clojure程序员会更清楚协议.

为了方便程序员,我们事先约定好了一系列的协议,Python会帮你实现这些协议,这一切都会让你的工作变得更轻松.

猜你喜欢

转载自blog.csdn.net/ltoddy/article/details/78700043
今日推荐