在Python中,多线程允许程序同时执行多个任务。他是通过创建线程并将任务分配给不同的线程来实现的,这有助于提高程序的执行效率,特别是在执行多个IO操作的时候,不过由于python的解释器锁(GIL),在执行cpu密集型任务的时候,多线程可能不会带来性能的提升
多线程经常用于IO密集型的任务,比如网络请求,文件读写等,例如在开发一个网络爬虫的时候,可以使用多线程同时下载多个网页,这样可以减少等待的IO操作的时间,提高程序的运行效率
import threading
import requests
def download_url(url):
print("开始 下载")
response = requests.get(url)
print("下载 结束")
urls = [
"http://www.example.com",
"http://www.example1.com",
"http://www.example2.com",
"http://www.example3.com",
"http://www.example4.com",
]
thread_s = [threading.Thread(target=download_url, args=(url,)) for url in urls]
for thread in thread_s:
thread.start()
for thread in thread_s:
thread.join()
print("所有任务下载完成")
多进程与多线程类似,也是并发执行的以中方式,但是每个进程都有自己独立的内存空间,因此进程间的通信要比线程间的通信要负责。多进程可以充分利用多核的CPU的优势,因此每个进程可以在不同的cpu核心上
多进程用于cpu密集型任务的计算,比如复杂的计算和数据处理。在数据分析科学计算等大量计算的资源应用当中,采用多进程可以有效提升程序的处理速度
from multiprocessing import Pool
def square(x):
return x * x
if __name__ == "__main__":
with Pool(4) as p:
numburs = range(10000)
result = p.map(square, numburs)
print(f'计算结束,{result}')
协程是以中比线程更加轻量级的执行单元,他是通过异步编程的模式来实现并发,协程依赖于时间循环,通过任务的挂起和回复来切换,这种模式非常适合执行IO密集型的操作,因为它可以在等待IO操作完成时,执行其他的任务,从而提高程序的运行效率
通常处理大量的网络连接,如在开发高性能的网络服务器或者异步web应用的时候。他允许单个线程高效管理和处理成千上万的并发连接,是实现高并发网络应用的理想选择
import asyncio
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession as session:
async with session.get(url) as response:
print("下载完成")
async def main():
urls = [
"http://www.example.com",
"http://www.example1.com",
"http://www.example2.com",
"http://www.example3.com",
"http://www.example4.com",
]
tasks = [fetch(url) for url in urls]
await asyncio.gether(*tasks)
asyncio.run(main())
线程是操作系统能够运算调度的最小的单位,他被包含在进程之中,是进程中的实际运作单位,每个线程都是独立调度和分派的基本单位,并且每个线程之间可以独立执行。操作系统调度器是负责管理线程的调度,这可能导致上下文切换的开销。
在Python中,是一种用户态的轻量级线程,由程序自身控制而非操作系统。协程依赖于异步边城,允许任务在等待IO操作的时候挂起,转而执行其他的任务。协程的调度完全由应用程序控制,减少了上下文切换的开销,但他们在一个线程内部执行。
尽管协程提供了搞笑的并发执行的能力,特别是在IO密集型任务的中,但多线程和多进程任然非常重要
对于需要大量计算的任务,多进程可以很好的利用多核cpu的计算能力。因为Python的全局解释器锁限制了同一时刻只能有一个线程执行python字节码,所以在CPU密集型任务中,使用多进程比使用协程或者多线程更能有效的提高程序的性能
很多现存的系统和库是基于线程模式设计的,对这些系统进行爱写以适应协程模型可能代价高昂。因此,在许需要与这些系统交互的时候,多线程任然是必须的。
在某些情况下,使用线程或进程可以简化任务的管理和编程模型。比如,对于并发执行的独立任务,直接创建多个进程或者多个线程可能比协程调度更直观更容易管理
不同的技术栈和应用场景有不同的最佳时间。例如图形界面程序更倾向于使用多线程来避免界面冻结,而高并发的网络服务可能会从协程中收益圣多。