欢送来到咱们的系列博客《Python全景系列》!在这个系列中,咱们将率领你从Python的基础知识开始,一步步深刻到高级话题,帮忙你把握这门弱小而灵便的编程语法。无论你是编程老手,还是有肯定根底的开发者,这个系列都将提供你须要的常识和技能。

这是本系列的第五篇,咱们将深入探讨Python中的并发编程,特地关注多线程和多过程的利用。咱们将先从基本概念开始,而后通过具体举例探讨每一种机制,最初分享一些实战经验以及一种优雅的编程技巧。

第一局部:多线程介绍

线程是操作系统中最小的执行单元。在单个程序或过程内,能够并发运行多个线程,共享过程的资源,如内存和文件描述符。

1.1 Python中的多线程

Python反对多线程编程,并提供了threading模块作为反对。这个模块提供了Thread类,咱们能够通过创立其实例并向其传递函数来创立新线程。当然,你也能够通过继承Thread类并重写run()办法来创立自定义线程。上面是一个多线程编程的例子:

import threadingdef print_numbers():    for i in range(10):        print(i)def print_letters():    for letter in 'abcdefghij':        print(letter)# 创立线程t1 = threading.Thread(target=print_numbers)t2 = threading.Thread(target=print_letters)# 启动线程t1.start()t2.start()# 期待线程完结t1.join()t2.join()

在下面的例子中,咱们定义了两个函数:一个打印数字,另一个打印字母。而后咱们创立了两个线程,每个线程的指标是执行这些函数。start()办法用于启动线程,而join()办法用于期待线程实现。

1.2 多线程的理论利用

只管Python的多线程因为全局解释器锁(GIL)的存在,并不能实现真正的并行,然而它们在I/O密集型工作中依然很有用。GIL是CPython解释器的一个互斥锁,保障在任何时刻只有一个线程在执行。这意味着在CPU密集型工作中,多线程可能不是最佳抉择,因为它们无奈充分利用多核CPU。

然而,在I/O密集型工作中,多线程可能进步程序性能。例如,如果一个程序须要从多个源下载文件,那么应用多线程能够使得当一个线程期待网络响应时,其余线程能够持续下载其余文件。这样,程序能够在同一时间从多个源下载文件,大大提高了效率。

第二局部:多过程介绍

过程是操作系统中独立的执行实体,每个过程都有本人的内存空间、文件描述符等资源。与线程不同,过程之间的资源

并不共享,每个过程都有本人独立的资源。

2.1 Python中的多过程

Python通过multiprocessing模块提供了多过程反对。相似于多线程,咱们能够通过创立Process类的实例并向其传递函数来创立新过程。咱们也能够通过继承Process类并重写run()办法来创立自定义过程。

以下是一个简略的多过程编程的例子:

import multiprocessingdef print_numbers():    for i in range(10):        print(i)def print_letters():    for letter in 'abcdefghij':        print(letter)# 创立过程p1 = multiprocessing.Process(target=print_numbers)p2 = multiprocessing.Process(target=print_letters)# 启动过程p1.start()p2.start()# 期待过程完结p1.join()p2.join()

这个例子和后面的多线程例子相似,不同的是这里咱们创立的是两个过程,而不是线程。

2.2 多过程的理论利用

多过程能够实现真正的并行,使得Python程序能够利用多核CPU。因而,对于CPU密集型工作,多过程通常比多线程更有劣势。另一方面,多过程的开销比多线程大,而且过程间的通信和同步也比线程间的更为简单。因而,对于I/O密集型工作,或者须要频繁通信的工作,多线程可能会是更好的抉择。

第三局部:优化并发编程的技巧

在Python中,concurrent.futures模块为多线程和多过程编程提供了高级接口,能够让咱们更加简洁地编写代码。

这个模块提供了ThreadPoolExecutorProcessPoolExecutor两个类,它们别离用于创立线程池和过程池。这两个类都实现了雷同的接口,你能够应用submit()办法提交工作,而后应用as_completed()函数期待工作实现。

上面是一个应用concurrent.futures模块的示例:

import concurrent.futuresdef print_numbers():   for i in range(10):       print(i)def print_letters():   for letter in 'abcdefghij':       print(letter)# 应用线程池with concurrent.futures.ThreadPoolExecutor() as executor:   future1 = executor.submit(print_numbers)   future2 = executor.submit(print_letters)   for future in concurrent.futures.as_completed([future1, future2]):       pass# 应用过程池with concurrent.futures.ProcessPoolExecutor() as executor:   future1 = executor.submit(print_numbers)   future2 = executor.submit(print_letters)   for future in concurrent.futures.as_completed([future1, future2]):       pass

在下面的例子中,咱们创立了线程池和过程池,而后向它们提交工作。能够看到,应用concurrent.futures模块,咱们的代码更加简洁,易读性和可维护性也有所提高。

总结

Python的多线程和多过程都是十分弱小的工具,能够帮忙咱们编写出更高效的程序。然而,它们也各有优缺点,须要咱们依据具体的工作和需要来抉择。同时,Python还提供了concurrent.futures模块,能够使咱们的并发编程变得更加简略和高效。

咱们心愿本文能帮忙你更好地了解和应用Python的多线程和多过程。如果你有任何疑难或者倡议,欢送在评论区留言。

【第一工夫取得Python全视角更新信息,请关注自己微信公众号: Python全视角】

如有帮忙,请多关注
集体微信公众号:【Python全视角】
TeahLead_KrisChang,10+年的互联网和人工智能从业教训,10年+技术和业务团队治理教训,同济软件工程本科,复旦工程治理硕士,阿里云认证云服务资深架构师,上亿营收AI产品业务负责人。