Python是一门高级编程语言,它支持多线程和多进程编程。但是线程与进程是操作系统层面的概念,因此在Python中,我们使用操作系统提供的多线程/多进程API来实现多线程/多进程编程。
本文将深度解析Python中的线程和进程,介绍它们的定义、工作原理以及使用方法。
线程是操作系统能够进行运算调度的最小单位,它被包含在进程中,是进程中真正执行的单位。相对于进程而言,线程是一个轻量级的存在,旨在实现一些简单的并行任务。在Python中,线程是_thread
和threading
模块中的重要概念。
在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
结果显示,使用进程和使用线程计算素数的结果都是正确的,但是进程的速度明显更快一些。这是因为进程之间独立运行,互不影响,具有很好的并行性。而线程之间共享进程的资源,容易出现竞争和阻塞,效率较低。