一文带你搞清晰Python的多线程和多进程

打印 上一主题 下一主题

主题 913|帖子 913|积分 2739

本文分享自华为云社区《Python中的多线程与多进程编程大全【python指南】》,作者:柠檬味拥抱。
Python作为一种高级编程语言,提供了多种并发编程的方式,其中多线程与多进程是最常见的两种方式之一。在本文中,我们将探究Python中多线程与多进程的概念、区别以及如何利用线程池与进程池来进步并发执行服从。
多线程与多进程的概念

多线程

多线程是指在同一进程内,多个线程并发执行。每个线程都拥有自己的执行栈和局部变量,但共享进程的全局变量、静态变量等资源。多线程恰当用于I/O麋集型任务,如网络请求、文件操作等,因为线程在等待I/O操作完成时可以释放GIL(全局表明器锁),答应其他线程执行。
多进程

多进程是指在操作系统中同时运行多个进程,每个进程都有自己独立的内存空间,相互之间不受影响。多进程恰当用于CPU麋集型任务,如计算麋集型算法、图像处理惩罚等,因为多进程可以利用多核CPU并行执行任务,进步整体运算速度。
线程池与进程池的先容

线程池

线程池是一种预先创建一定命量的线程并维护这些线程,以便在需要时重复利用它们的技术。线程池可以减少线程创建和销毁的开销,进步线程的重复利用率。在Python中,可以利用concurrent.futures.ThreadPoolExecutor来创建线程池。
进程池

进程池类似于线程池,不同之处在于进程池预先创建一定命量的进程并维护这些进程,以便在需要时重复利用它们。进程池可以利用多核CPU并行执行任务,进步整体运算速度。在Python中,可以利用concurrent.futures.ProcessPoolExecutor来创建进程池。
线程池与进程池的应用示例

下面是一个简单的示例,演示了如何利用线程池和进程池来执行一组任务。
  1. import concurrent.futures
  2. import time
  3. def task(n):
  4.     print(f"Start task {n}")
  5.     time.sleep(2)
  6.     print(f"End task {n}")
  7.     return f"Task {n} result"
  8. def main():
  9.     # 使用线程池
  10.     with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
  11.         results = executor.map(task, range(5))
  12.         for result in results:
  13.             print(result)
  14.     # 使用进程池
  15.     with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
  16.         results = executor.map(task, range(5))
  17.         for result in results:
  18.             print(result)
  19. if __name__ == "__main__":
  20.     main()
复制代码
在上面的示例中,我们定义了一个task函数,模拟了一个耗时的任务。然后,我们利用ThreadPoolExecutor创建了一个线程池,并利用map方法将任务提交给线程池执行。同样地,我们也利用ProcessPoolExecutor创建了一个进程池,并利用map方法提交任务。末了,我们打印出每个任务的效果。
线程池与进程池的性能比较

虽然线程池与进程池都可以用来实现并发执行任务,但它们之间存在一些性能上的差异。
线程池的优势


  • 轻量级: 线程比进程更轻量级,创建和销毁线程的开销比创建和销毁进程要小。
  • 共享内存: 线程共享同一进程的内存空间,可以方便地共享数据。
  • 低开销: 在切换线程时,线程只需生存和恢复栈和寄存器的状态,开销较低。
进程池的优势


  • 真正的并行: 进程可以利用多核CPU真正并行执行任务,而线程受到GIL的限制,在多核CPU上无法真正并行执行。
  • 稳定性: 进程之间相互独立,一个进程崩溃不会影响其他进程,进步了程序的稳定性。
  • 资源隔离: 每个进程有自己独立的内存空间,可以避免多个线程之间的内存共享题目。
性能比较示例

下面是一个简单的性能比较示例,演示了线程池和进程池在执行CPU麋集型任务时的性能差异。
  1. import concurrent.futures
  2. import time
  3. def cpu_bound_task(n):
  4.     result = 0
  5.     for i in range(n):
  6.         result += i
  7.     return result
  8. def main():
  9.     start_time = time.time()
  10.     # 使用线程池执行CPU密集型任务
  11.     with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
  12.         results = executor.map(cpu_bound_task, [1000000] * 3)
  13.     print("Time taken with ThreadPoolExecutor:", time.time() - start_time)
  14.     start_time = time.time()
  15.     # 使用进程池执行CPU密集型任务
  16.     with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
  17.         results = executor.map(cpu_bound_task, [1000000] * 3)
  18.     print("Time taken with ProcessPoolExecutor:", time.time() - start_time)
  19. if __name__ == "__main__":
  20.     main()
复制代码
在上面的示例中,我们定义了一个cpu_bound_task函数,模拟了一个CPU麋集型任务。然后,我们利用ThreadPoolExecutor和ProcessPoolExecutor分别创建线程池和进程池,并利用map方法提交任务。末了,我们比较了两种方式执行任务所花费的时间。
通过运行以上代码,你会发现利用进程池执行CPU麋集型任务的时间通常会比利用线程池执行快,这是因为进程池可以利用多核CPU真正并行执行任务,而线程池受到GIL的限制,在多核CPU上无法真正并行执行。
当思量如何实现一个可以或许同时下载多个文件的程序时,线程池和进程池就成为了很有用的工具。让我们看看如何用线程池和进程池来实现这个功能。
首先,我们需要导入相应的库:
  1. import concurrent.futures
  2. import requests
  3. import time
复制代码
然后,我们定义一个函数来下载文件:
  1. def download_file(url):
  2.     filename = url.split("/")[-1]
  3.     print(f"Downloading {filename}")
  4.     response = requests.get(url)
  5.     with open(filename, "wb") as file:
  6.         file.write(response.content)
  7.     print(f"Downloaded {filename}")
  8.     return filename
复制代码
接下来,我们定义一个函数来下载多个文件,这里我们利用线程池和进程池来分别执行:
  1. def download_files_with_thread_pool(urls):
  2.     start_time = time.time()
  3.     with concurrent.futures.ThreadPoolExecutor() as executor:
  4.         results = executor.map(download_file, urls)
  5.     print("Time taken with ThreadPoolExecutor:", time.time() - start_time)
  6. def download_files_with_process_pool(urls):
  7.     start_time = time.time()
  8.     with concurrent.futures.ProcessPoolExecutor() as executor:
  9.         results = executor.map(download_file, urls)
  10.     print("Time taken with ProcessPoolExecutor:", time.time() - start_time)
复制代码
末了,我们定义一个主函数来测试这两种方式的性能:
  1. def main():
  2.     urls = [
  3.         "https://www.example.com/file1.txt",
  4.         "https://www.example.com/file2.txt",
  5.         "https://www.example.com/file3.txt",
  6.         # Add more URLs if needed
  7.     ]
  8.     download_files_with_thread_pool(urls)
  9.     download_files_with_process_pool(urls)
  10. if __name__ == "__main__":
  11.     main()
复制代码
通过运行以上代码,你可以比较利用线程池和进程池下载文件所花费的时间。通常情况下,当下载大量文件时,利用进程池的性能会更好,因为它可以利用多核CPU实现真正的并行下载。而利用线程池则更恰当于I/O麋集型任务,如网络请求,因为线程在等待I/O操作完成时可以释放GIL,答应其他线程执行。
这个例子展示了如何利用线程池和进程池来进步并发下载文件的服从,同时也夸大了根据任务特点选择符合的并发编程方式的重要性。
并发编程中的注意事项

虽然线程池与进程池提供了方便的并发执行任务的方式,但在实际应用中还需要注意一些题目,以避免出现潜在的并发题目和性能瓶颈。
共享资源的同步


  • 在多线程编程中,共享资源的访问需要进行同步,以避免竞争条件和数据不一致性题目。可以利用锁、信号量等同步机制来掩护关键资源的访问。
  • 在多进程编程中,由于进程之间相互独立,共享资源的同步相对简单,可以利用进程间通信(如管道、队列)来通报数据,避免数据竞争题目。
内存消耗与上下文切换


  • 创建大量线程或进程可能会导致内存消耗增长,甚至引起内存泄漏题目。因此,在设计并发程序时需要注意资源的合理利用,避免创建过多的线程或进程。
  • 上下文切换也会带来一定的开销,特别是在频繁切换的情况下。因此,在选择并发编程方式时,需要综合思量任务的特点和系统资源的限制,以及上下文切换的开销。
异常处理惩罚与任务超时


  • 在并发执行任务时,需要注意异常处理惩罚机制,及时捕获和处理惩罚任务中可能出现的异常,以包管程序的稳定性和可靠性。
  • 另外,为了避免任务阻塞导致整个程序停滞,可以设置任务的超时时间,并在超时后取消任务或进行相应的处理惩罚。
最佳实践与建议

在实际应用中,为了编写高效、稳定的并发程序,可以遵循以下一些最佳实践和建议:

  • 合理设置并发度: 根据系统资源和任务特点,合理设置线程池或进程池的巨细,避免创建过多的线程或进程。
  • 合理分配任务: 根据任务的类型和特点,合理分配任务到线程池或进程池中,以充分利用系统资源。
  • 注意异常处理惩罚: 在任务执行过程中及时捕获和处理惩罚异常,包管程序的稳定性和可靠性。
  • 监控与调优: 利用监控工具和性能分析工具对并发程序进行监控和调优,及时发现和解决性能瓶颈和潜在题目。
通过遵循以上最佳实践和建议,可以编写出高效、稳定的并发程序,进步程序的执行服从和性能。同时,也可以避免一些常见的并发编程陷阱和题目,确保程序的质量和可靠性。
总结

本文先容了在Python中利用线程池和进程池来实现并发编程的方法,并提供了相应的代码示例。首先,我们讨论了多线程和多进程的概念及其在并发编程中的应用场景。然后,我们深入探究了线程池和进程池的工作原理以及它们之间的性能比较。
在代码示例部分,我们演示了如何利用线程池和进程池来执行多个任务,其中包括下载多个文件的示例。通过比较两种方式执行任务所花费的时间,我们可以更好地了解它们在不同场景下的优劣势。
此外,文章还提供了一些并发编程中的注意事项和最佳实践,包括共享资源的同步、内存消耗与上下文切换、异常处理惩罚与任务超时等。这些建议有助于开辟者编写高效、稳定的并发程序,进步程序的执行服从和性能。
总的来说,线程池和进程池是Python中强盛的工具,可以或许帮助开辟者轻松实现并发编程,并充分利用计算资源。选择符合的并发编程方式,并联合实际场景和任务特点,可以编写出高效、可靠的并发程序,提拔应用的性能和用户体验。
点击关注,第一时间了解华为云新鲜技术~
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表