深度解析Python线程和进程

2023-12-15Python编程
6

深度解析Python线程和进程

Python是一门高级编程语言,它支持多线程和多进程编程。但是线程与进程是操作系统层面的概念,因此在Python中,我们使用操作系统提供的多线程/多进程API来实现多线程/多进程编程。

本文将深度解析Python中的线程和进程,介绍它们的定义、工作原理以及使用方法。

线程

定义

线程是操作系统能够进行运算调度的最小单位,它被包含在进程中,是进程中真正执行的单位。相对于进程而言,线程是一个轻量级的存在,旨在实现一些简单的并行任务。在Python中,线程是_threadthreading模块中的重要概念。

工作原理

在Python中,线程是由操作系统负责调度的。当我们创建线程并启动它后,它会和主线程一起被放入系统的调度队列中,由操作系统负责决定哪些线程可以运行,并通过时间片轮转的方式进行交替执行。

使用方法

引入_thread模块,使用start_new_thread()函数创建线程。

import _thread

# 定义线程函数
def print_time(threadName, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print(f"{threadName}:{time.ctime(time.time())}")

# 创建两个线程
try:
    _thread.start_new_thread(print_time, ("Thread 1", 1,))
    _thread.start_new_thread(print_time, ("Thread 2", 2,))
except:
    print("Error: 无法启动线程")

# 等待所有线程完成
while 1:
    pass

进程

定义

进程是一个具有一定独立功能的程序关于某个数据集合上的一次运行活动。在一个程序中可以同时运行多个进程,每个进程之间是独立的、不影响的、互相隔离的。在Python中,进程是multiprocessing模块中的重要概念。

工作原理

在Python中,进程也是由操作系统负责调度的。当我们创建进程并启动它后,它会被划分到不同的CPU核心并分别调度运行,不同进程之间无法共享数据,通过IPC(inter process communication)机制进行进程间通信。

使用方法

引入multiprocessing模块,使用Process类创建进程。

from multiprocessing import Process

# 定义进程函数
def print_time(processName):
    count = 0
    while count < 5:
        time.sleep(1)
        count += 1
        print(f"{processName}:{time.ctime(time.time())}")

# 创建两个进程
if __name__ == '__main__':
    p1 = Process(target=print_time, args=("Process 1",))
    p2 = Process(target=print_time, args=("Process 2",))

    # 启动进程
    p1.start()
    p2.start()

    # 等待子进程完成后,再继续往后执行
    p1.join()
    p2.join()

示例

下面演示使用Python的多线程和多进程来处理一个耗时的任务,比较它们的运行速度。

import time
from threading import Thread
from multiprocessing import Process

def count_prime_number(start, end):
    # 统计素数的个数
    count = 0
    for num in range(start, end+1):
        # 素数定义:只能被1和本身整除的数
        if num > 1:
            for i in range(2, num):
                if num % i == 0:
                    break
            else:
                count += 1
    print(f"从{start}到{end}之间的素数个数为{count}")

if __name__ == '__main__':
    start_time = time.time()

    # 创建两个线程分别计算1~5000和5001~10000之间的素数
    t1 = Thread(target=count_prime_number, args=(1, 5000))
    t2 = Thread(target=count_prime_number, args=(5001, 10000))

    # 创建两个进程分别计算1~5000和5001~10000之间的素数
    p1 = Process(target=count_prime_number, args=(1, 5000))
    p2 = Process(target=count_prime_number, args=(5001, 10000))

    print("计算素数(使用线程):")
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("计算素数(使用进程):")
    p1.start()
    p2.start()
    p1.join()
    p2.join()

    end_time = time.time()
    print(f"程序运行时间:{end_time-start_time}s")

执行结果如下:

计算素数(使用线程):
从1到5000之间的素数个数为669
从5001到10000之间的素数个数为670
计算素数(使用进程):
从5001到10000之间的素数个数为670
从1到5000之间的素数个数为669
程序运行时间:5.438058376312256s

结果显示,使用进程和使用线程计算素数的结果都是正确的,但是进程的速度明显更快一些。这是因为进程之间独立运行,互不影响,具有很好的并行性。而线程之间共享进程的资源,容易出现竞争和阻塞,效率较低。

The End

相关推荐

解析Python中的eval()、exec()及其相关函数
Python中有三个内置函数eval()、exec()和compile()来执行动态代码。这些函数能够从字符串参数中读取Python代码并在运行时执行该代码。但是,使用这些函数时必须小心,因为它们的不当使用可能会导致安全漏洞。...
2023-12-18 Python编程
117

Python下载网络文本数据到本地内存的四种实现方法示例
在Python中,下载网络文本数据到本地内存是常见的操作之一。本文将介绍四种常见的下载网络文本数据到本地内存的实现方法,并提供示例说明。...
2023-12-18 Python编程
101

Python 二进制字节流数据的读取操作(bytes与bitstring)
来给你详细讲解下Python 二进制字节流数据的读取操作(bytes与bitstring)。...
2023-12-18 Python编程
120

Python3.0与2.X版本的区别实例分析
Python 3.x 是 Python 2.x 的下一个重大版本,其中有一些值得注意的区别。 Python 3.0中包含了许多不兼容的变化,这意味着在迁移到3.0之前,必须进行代码更改和测试。本文将介绍主要的差异,并给出一些实例来说明不同点。...
2023-12-18 Python编程
34

python如何在终端里面显示一张图片
要在终端里显示图片,需要使用一些Python库。其中一种流行的库是Pillow,它有一个子库PIL.Image可以加载和处理图像文件。要在终端中显示图像,可以使用如下的步骤:...
2023-12-18 Python编程
91

Python图像处理实现两幅图像合成一幅图像的方法【测试可用】
在Python中,我们可以使用Pillow库来进行图像处理。具体实现两幅图像合成一幅图像的方法如下:...
2023-12-18 Python编程
103