最近有用Python标准模板库里的线程池实现一些东西,发现非常好用,记录一下。
非模板库实现
之前自己实现线程池呢,有两种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| def func(x, return_dict):
time.sleep(1)
print(x << 2)
return_dict[x] = x * x
def PoolByUser():
pool = list()
return_dict = dict()
for i in range(10):
p = threading.Thread(target=func, args=(i, return_dict))
p.start()
pool.append(p)
for p in pool:
p.join()
print(return_dict)
|
第一种方式,先创建list用来保存线程。return_dict 为保存结果的字典。多线程比多进程实现的好处在于,主进程中的变量在多个子线程中是共享的,无需复杂的操作。
结束时,需要挨个停止。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| task_queue = Queue()
need_run = True
return_dict = dict()
def task_func(return_dit):
while need_run:
try:
x = task_queue.get(timeout=2)
return_dit.update({x: x * x})
except:
pass
def PoolUseTaskQueue():
t_list = list()
for i in range(10):
t = threading.Thread(target=task_func, args=(return_dict,))
t.start()
t_list.append(t)
[task_queue.put(i) for i in range(20)]
global need_run
need_run = False
for t in t_list:
t.join()
print(return_dict)
|
第二种方式,通过模拟任务队列的方式实现。先创建多个线程,然后将需要的输入参数传入队列中,每个子线程通过任务队列来获取输入的参数。标准模板库中的队列对象内部,已经实现了锁的功能,无需自己实现。
标准模板库实现
标准模板库中实现多线程和多进程的方法十分简单!
1
2
3
4
5
6
| pool = multiprocessing.Pool(4)
pool.apply(func, args=("First",))
pool.apply(func, args=("Second",))
pool.apply(func, args=("Third",))
pool.close()
pool.join()
|
如上,只需创建多进程池,然后将方法添加池中,既可。相关函数功能简介如下:
- apply - 最简单的方式,传入参数为方法,和该方法所需的入参。
- apply_async - 上述方式的异步实现模式。
- map - 传入的参数为方法,以及该方法所需的参数迭代器,适用于单个入參的方法,当然也可以把多个入參当作一个结构体传入。
- map_async - 上述方式的异步实现模式。
- starmap - 与map不同之处在于,它可以将多个入參一同传入,而不用组成结构体。
- starmap_async -上述方式的异步实现模式。
multiprocessing模块还有 多线程池——ThreadPool,使用的方式和多进程池的方式一样。
进程间通信
进程间的通信方式不同于线程间。子进程在创建时,已经将父进程中的变量copy了一份,导致了每个子进程中 之前相同的变量都不相同了,因此不能通过父进程的变量进行子进程间的通信。
这时候需要第三方的机构来做一个类似中间人的过程。
信号、信号量、共享内存、socket、管道、实体文件等等。
multiprocess中Manager对象,可以实例化dict、list对象出来,用于子进程间的通信。
也可以通过multiprocess中的Queue。
Author
Alfons
LastMod
2019-06-26
License
Creative Commons BY-NC-ND 3.0