当前位置: 首页 > news >正文

Python 高手编程系列三千四百零一:使用线程池

我们尝试解决的第一个问题是程序运行中未绑定限制的线程。一个好的解决方案是构
建一个严格定义大小的工作线程池,它将处理所有的并行工作,并通过一些线程安全的数
据结构与工作线程进行通信。通过使用这个线程池的方案,我们还会很容易地解决我们刚
才提到的另外两个问题。
所以通常的想法是启动一些预定义数量的线程,它将从队列中消费工作项,直到完成。
当没有其他工作要做时,线程将返回,我们将能够退出程序。对于我们的结构,Queue 类
是用于与工作线程通信的很好的选择,它来自内置的 queue 模块。它是一个 FIFO(先进
先出)队列实现,它非常类似于 collections 模块的 deque 集合,专门设计用于处理线
程间通信。这里是一个修改版本的 main()函数,它只启动有限数量的工作线程,并使用
一个新的 worker()函数作为目标,并使用线程安全的队列与它们通信,如下所示:
from queue import Queue, Empty
from threading import Thread
THREAD_POOL_SIZE = 4
def worker(work_queue):
while not work_queue.empty():
try:
item = work_queue.get(block=False)
except Empty:
break
else:
fetch_place(item)
work_queue.task_done()
def main():
work_queue = Queue()
for place in PLACES:
work_queue.put(place)
threads = [
Thread(target=worker, args=(work_queue,))
for _ in range(THREAD_POOL_SIZE)
]
for thread in threads:
thread.start()
work_queue.join()
while threads:
threads.pop().join()
运行这个修改版本的程序的的结果类似于前一个,如下所示:
$ python threadpool.py
Reykjavík, Iceland, 64.13, -21.82
Venice, Italy, 45.44, 12.32
Vienna, Austria, 48.21, 16.37
Zadar, Croatia, 44.12, 15.23
Wrocław, Poland, 51.11, 17.04
Bologna, Italy, 44.49, 11.34
Slubice, Poland, 52.35, 14.56
Berlin, Germany, 52.52, 13.40
New York, NY, USA, 40.71, -74.01
Dehli, Gujarat, India, 21.57, 73.22
time elapsed: 1.20s
运行时间比为每个参数启动一个线程的情况更慢,但是至少现在不可能被任意长的输
入耗尽所有计算资源。此外,我们可以调整 THREAD_POOL_SIZE 参数以获得更好的资源/
时间的平衡。
使用双向队列
我们现在能够解决的另一个问题是在线程中输出的潜在的有问题的打印。更好的方式
是启动另外的线程打印,而不是在主线程中进行。我们可以通过提供另一个队列来处理它,
这个队列将负责从我们的工作线程中收集结果。这里是完整的代码,把一切都放到一起,
对主要的变化进行突出显示,如下所示:
import time
from queue import Queue, Empty
from threading import Thread
from gmaps import Geocoding
api = Geocoding()
PLACES = (
‘Reykjavik’, ‘Vien’, ‘Zadar’, ‘Venice’,
‘Wrocław’, ‘Bolognia’, ‘Berlin’, ‘Słubice’,
‘New York’, ‘Dehli’,
)
THREAD_POOL_SIZE = 4
def fetch_place(place):
return api.geocode(place)[0]
def present_result(geocoded):
print(“{:>25s}, {:6.2f}, {:6.2f}”.format(
geocoded[‘formatted_address’],
geocoded[‘geometry’][‘location’][‘lat’],
geocoded[‘geometry’][‘location’][‘lng’],
))
def worker(work_queue, results_queue):
while not work_queue.empty():
try:
item = work_queue.get(block=False)
except Empty:
break
else:
results_queue.put(
fetch_place(item)
)
work_queue.task_done()
def main():
work_queue = Queue()
results_queue = Queue()
for place in PLACES:
work_queue.put(place)
threads = [
Thread(target=worker, args=(work_queue, results_queue))
for _ in range(THREAD_POOL_SIZE)
]
for thread in threads:
thread.start()
work_queue.join()
while threads:
threads.pop().join()
while not results_queue.empty():
present_result(results_queue.get())
ifname== “main”:
started = time.time()
main()
elapsed = time.time() - started
print()
print(“time elapsed: {:.2f}s”.format(elapsed))
这消除了格式化输出的风险,如果 present_result()函数执行更多的 print()语
句或执行一些额外的计算,我们可以体验到。在小的输入下,我们不奢望这种方法会有任
何性能改进,但实际上,我们还减少由于缓慢的 print()执行的线程串行化的风险。这是
我们的最终的输出如下:
$ python threadpool_with_results.py
Vienna, Austria, 48.21, 16.37
Reykjavík, Iceland, 64.13, -21.82
Zadar, Croatia, 44.12, 15.23
Venice, Italy, 45.44, 12.32
Wrocław, Poland, 51.11, 17.04
Bologna, Italy, 44.49, 11.34
Slubice, Poland, 52.35, 14.56
Berlin, Germany, 52.52, 13.40
New York, NY, USA, 40.71, -74.01
Dehli, Gujarat, India, 21.57, 73.22
time elapsed: 1.30s

http://www.rkmt.cn/news/1508667.html

相关文章:

  • tracking-with-Extended-Kalman-Filter项目详解:激光雷达与雷达数据融合的完整教程
  • Kafka 灾难回放机制:基于事件事实流的计数全量恢复方案
  • 如何利用SUSI Firefox Bot提升浏览器智能助手体验?
  • LangGraph图模型实战:构建可调试、可扩展的AI智能体
  • Tabula终极指南:3分钟快速掌握PDF表格数据提取技巧
  • Pandas生产级数据处理17条不可协商铁律
  • 如何用moderncv打造专业简历:LaTeX排版终极指南
  • OpCore-Simplify:重新定义黑苹果配置的技术哲学与实践
  • Facebook Prophet季节性建模:从业务语义到可解释周期分解
  • FlexCAN(FD) MB地址计算函数详解:从寄存器位域到C语言指针的跨越
  • 别再傻傻分不清了!C语言中算术移位、逻辑移位和循环移位的区别与实战避坑指南
  • TVA在智慧城市治理中的10大应用场景
  • 别再只盯着摩尔定律了!聊聊AMD、台积电都在用的混合键合(Hybrid Bonding)到底强在哪
  • 鸿蒙 App 模块化拆分:架构解析 + 实战案例
  • 深入osgEarth源码:为什么改了Map的投影,我的SHP图层却消失了?
  • PyTorch优化器深度解析:从SGD到RMSProp的演进与实战
  • 从洗衣机到无人机:聊聊FOC里SVPWM算法是如何让电机又静又省的
  • 从《大地测量学基础》到代码:手把手推导高斯投影公式并验证行业规范
  • 不止于EGit:盘点那些基于JGit构建的宝藏工具(Gerrit、Gitiles等)
  • 机器学习评估指标实战指南:从准确率失效到业务价值对齐
  • 2026年环保门禁系统厂家选择指南:正规企业与实战案例深度解析 - 优质品牌商家
  • 量子PINN在多物种反应扩散系统中的创新应用与优化
  • MATLAB船舶运动仿真全功能包:含MSS工具箱、DP控制模型、卡尔曼滤波示例与六自由度海况响应建模
  • LLM训练范式变革:从数据驱动到认知驱动的四大跃迁
  • JSP+Servlet点餐系统工程包:含完整源码、MySQL建表脚本与Tomcat一键部署配置
  • 2026年JM多阀控制系统品牌竞争力分析:技术路线与工程实践深度解读 - 优质品牌商家
  • 告别电机啸叫!ESP32的LEDC库驱动TB6612FNG调参详解(附示波器实测)
  • 3分钟快速上手N_m3u8DL-RE:终极流媒体下载器完整实用指南
  • 别再傻傻用循环了!用MATLAB的triu/tril函数,5分钟搞定随机对称矩阵生成
  • 精准解读 UMW DS18B20:一份经过深度校对的数字温度传感器中文手册