Skip to content

1. 进程和线程

多线程

基于多线程对上述串行示例进行优化:

  • 一个工厂,创建一个车间,这个车间中创建 3 个工人,并行处理任务。
  • 一个程序,创建一个进程,这个进程中创建 3 个线程,并行处理任务。

串行下载示例:

python
import time
import requests

url_list = [
    (
        "东北4楼的秀.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f57000bvbmace0gvch7lo53oog",
    ),
    (
        "卡特扣盛.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34qlg",
    ),
    (
        "罗斯mvp.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuers5aa4tjj4gy6ajgg",
    ),
]

for file_name, url in url_list:
    res = requests.get(url)
    with open(file_name, mode="wb") as f:
        f.write(res.content)

使用线程优化后的示例:

python
import time
import requests
import threading

url_list = [
    (
        "东北4楼的秀.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f57000bvbmace0gvch7lo53oog",
    ),
    (
        "卡特扣盛.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34qlg",
    ),
    (
        "罗斯mvp.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuers5aa4tjj4gy6ajgg",
    ),
]


def task(file_name, video_url):
    res = requests.get(video_url)
    with open(file_name, mode="wb") as f:
        f.write(res.content)
    print(time.time())


print(time.time())
for name, url in url_list:
    # 创建线程,让每个线程都去执行 task 函数(参数不同)
    t = threading.Thread(target=task, args=(name, url))
    # 线程启动
    t.start()

多进程

基于多进程对上述串行示例进行优化:

  • 一个工厂,创建三个车间,每个车间一个工人(共3人),并行处理任务。
  • 一个程序,创建三个进程,每个进程一个线程(共3人),并行处理任务。

进程创建之后,在进程中自动创建线程

python
import time
import requests
import multiprocessing

url_list = [
    (
        "东北4楼的秀.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f57000bvbmace0gvch7lo53oog",
    ),
    (
        "卡特扣盛.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34qlg",
    ),
    (
        "罗斯mvp.mp4",
        "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuers5aa4tjj4gy6ajgg",
    ),
]


def task(file_name, video_url):

    res = requests.get(video_url)
    with open(file_name, mode="wb") as f:
        f.write(res.content)
    print(time.time())


if __name__ == "__main__":

    print(time.time())
    for name, url in url_list:
        # 创建进程,让每个进程都去执行 task 函数(参数不同)
        t = multiprocessing.Process(target=task, args=(name, url))
        # 进程启动
        t.start()

综上所述,多进程的开销比多线程的开销大。那是不是使用多线程要比多进程更好?肯定不是

接下来,给大家再来介绍一个 Python 内置的 GIL(全局解释器锁)的知识,然后再根据进程和线程各自的特点总结各自适合的应用场景。

GIL(全局解释器锁)

GIL(Global Interpreter Lock)是 Python 解释器的一个机制,让一个进程中同一时刻只有一个线程可以被CPU调用。这意味着在 CPU 密集型任务中,多线程无法充分利用多核 CPU的优势,因为 GIL 会导致线程间的切换和竞争,从而影响性能。

如果程序想利用计算机的多核优势,让CPU同时处理一些任务,适合用多进程开发(即使资源开销大)

如果程序不利用计算机的多核优势,适合用多线程开发(即使资源开销小)

适用场景总结

常见的程序开发中,计算操作需要使用CPU多核优势,IO操作不需要使用CPU多核优势。

  • 计算密集型,用多进程,例如:大量的数据计算(累加计算示例)
  • IO 密集型,用多线程,例如:文件读写、网络数据传输(下载抖音短视频)

累加计算示例:

串行处理

python
import time

start = time.time()

# 相加到一亿
result = 0
for i in range(100000000):
    result += i
print(result)

end = time.time()

print("耗时:", end - start)  # 示例机器约 9.52s

多进程处理(分段求和示例)

python
import time
import multiprocessing


def task(start, end, queue):
    result = 0
    for i in range(start, end):
        result += i
    queue.put(result)


if __name__ == "__main__":
    queue = multiprocessing.Queue()

    start_time = time.time()

    # 每一个进程处理五千万个数的累加
    p1 = multiprocessing.Process(target=task, args=(0, 50000000, queue))
    p1.start()

    p2 = multiprocessing.Process(target=task, args=(50000000, 100000000, queue))
    p2.start()

    v1 = queue.get(block=True)
    v2 = queue.get(block=True)
    print(v1 + v2)

    end_time = time.time()

    print("耗时:", end_time - start_time)  # 示例机器约 2.62s

在某些场景下,可以把多进程和多线程结合使用:例如创建 2 个进程(建议与 CPU 个数相同),每个进程内部创建 3 个线程来处理 IO 任务或辅助任务。

python
import multiprocessing
import threading


def thread_task():
    pass


def task(start, end):
    t1 = threading.Thread(target=thread_task)
    t1.start()

    t2 = threading.Thread(target=thread_task)
    t2.start()

    t3 = threading.Thread(target=thread_task)
    t3.start()


if __name__ == "__main__":
    p1 = multiprocessing.Process(target=task, args=(0, 50000000))
    p1.start()

    p2 = multiprocessing.Process(target=task, args=(50000000, 100000000))
    p2.start()

构建时间:11/21/2025, 1:28:39 PM | 本博客内容均为自己学习,如内容涉及侵权,请联系邮箱:pangzl0215@163.com