让我们首先了解计算机体系结构中线程的概念。
在计算中,进程是正在执行的计算机程序的实例。任何过程都有 3 个基本组件:
线程是进程中可以安排执行的实体。此外,它是可以在操作系统(操作系统)中执行的最小处理单元。
简单来说,线程是程序中可以独立于其他代码执行的此类指令序列。为简单起见,您可以假设线程只是进程的子集!
线程在线程控制块 (TCB) 中包含所有这些信息:
请参考下图以了解进程与其线程之间的关系:
一个进程中可以存在多个线程,其中:
请参考下图以了解内存中如何存在多个线程:
在Python中,线程模块提供了一个非常简单直观的API,用于在程序中生成多个线程。
让我们考虑一个使用线程模块的简单示例:
import threading
def print_cube(num):
"""用于打印给定数字的多维数据集的函数"""
print("Cube: {}".format(num * num * num))
def print_square(num):
"""函数打印给定数值的平方"""
print("Square: {}".format(num * num))
if __name__ == "__main__":
# 创建线程
t1 = threading.Thread(target=print_square, args=(10,))
t2 = threading.Thread(target=print_cube, args=(10,))
# 启动线程1
t1.start()
# 启动线程2
t2.start()
# 等待线程1完全执行
t1.join()
# 等待线程2完全执行
t2.join()
# 两个线程都已完全执行
print("Done!")
运行结果:
让我们试着理解上面的代码:
要导入线程模块,我们需要:
import threading
要创建一个新线程,我们创建一个 Thread 类的对象。它需要以下参数:
在上面的例子中,我们创建了2个具有不同目标函数的线程:
t1 = threading.Thread(target=print_square, args=(10,))
t2 = threading.Thread(target=print_cube, args=(10,))
要启动线程,我们使用 Thread 类的 start 方法。
t1.start()
t2.start()
一旦线程启动,当前程序(你可以把它想象成一个主线程)也会继续执行。为了停止当前程序的执行,直到线程完成,我们使用连接方法。
t1.join()
t2.join()
因此,当前程序将首先等待 t1 的完成,然后等待 t2 完成。完成后,将执行当前程序的其余语句。
考虑下图,以更好地了解上述程序的工作原理:
考虑下面给出的python程序,其中我们为每个任务打印线程名称和相应的进程:
import threading
import os
def task1():
print("任务1分配给线程: {}".format(threading.current_thread().name))
print("运行任务1的进程ID: {}".format(os.getpid()))
def task2():
print("任务2分配给线程: {}".format(threading.current_thread().name))
print("运行任务2的进程ID: {}".format(os.getpid()))
if __name__ == "__main__":
# 打印当前进程的ID
print("运行主程序的进程ID: {}".format(os.getpid()))
# 打印主线程名称
print("主线程名称: {}".format(threading.current_thread().name))
# 创建线程
t1 = threading.Thread(target=task1, name='t1')
t2 = threading.Thread(target=task2, name='t2')
# 启动线程
t1.start()
t2.start()
# 等待所有线程完成
t1.join()
t2.join()
运行结果:
让我们试着理解上面的代码:
我们使用 os.getpid() 函数来获取当前进程的 ID。
print("运行主程序的进程ID: {}".format(os.getpid()))
从输出中可以清楚地看出,所有线程的进程 ID 都保持不变。
我们使用threading.main_thread() 函数来获取主线程对象。在正常情况下,主线程是启动Python解释器的线程。线程对象的 name 属性用于获取线程的名称。
print("主线程名称: {}".format(threading.main_thread().name))
我们使用 threading.current_thread() 函数来获取当前线程对象。
print("任务1分配的线程: {}".format(threading.current_thread().name))
下图阐明了上述概念: