摘要:在多线程程序中,原本按顺序运行的任务可以同时执行,这使得它对于涉及大量计算、实时数据处理或交互式用户界面的应用程序特别有用。例如,在游戏中,我们可以使用多线程同时收听音频和观看视频。
多线程是一种编程概念,它允许多个线程在单个程序中并发运行。线程是最小的执行单位,使用多个线程可以提高应用程序的性能和响应能力。
在多线程程序中,原本按顺序运行的任务可以同时执行,这使得它对于涉及大量计算、实时数据处理或交互式用户界面的应用程序特别有用。例如,在游戏中,我们可以使用多线程同时收听音频和观看视频。
多线程的美妙之处在于它能够利用现代多核处理器,使程序更快、更高效。一般来说,一个 N 核 CPU 可以同时运行 N 个线程,但是许多现代 CPU 支持像 Intel 的 Hyper-Threading 或 AMD 的 SMT 这样的技术,允许每个内核同时处理两个线程。
您可能想知道为什么需要编写一个可以同时执行线程的程序。好吧,在许多情况下,同时执行多项任务是必不可少的。例如,考虑一个 PC 游戏,您可以在其中同时收听声音和观看视频。这是一个基本但清晰的示例,说明了为什么多线程很重要。
多线程还通过使任务能够并行执行来节省时间。但是,它与多处理不同:多线程在同一进程中使用线程,而真正的并行性是通过多处理实现的,其中多个进程在不同的内核上运行。
要了解多线程的工作原理,我们首先需要更深入地了解什么是线程和进程。
线程是可以由操作系统独立管理的最小执行单元。它表示可以并发运行的独立指令序列,通常与同一进程中的其他线程共享资源,例如内存和文件句柄。线程使程序能够同时执行多个任务或提高响应能力。
线程通常将其状态和信息存储在称为线程控制块 (TCB) 的结构中。TCB 包含线程 ID、程序计数器、寄存器状态和调度信息等数据,使操作系统能够有效地管理线程执行。
线程标识符:分配给线程的唯一编号或名称,用于将其与程序中的其他线程区分开来。Program Counter:一个寄存器,用于跟踪线程要执行的下一条指令。Stack Pointer:指向线程堆栈顶部的寄存器,用于存储局部变量和函数调用信息。线程状态:线程的当前条件或状态,例如 running、waiting 或 terminated。Thread Register Set:存储线程执行上下文的寄存器(如程序计数器、堆栈指针等)的集合。父进程指针:指向创建线程的进程的引用或指针,允许线程访问其父进程的资源或上下文。在 Python 中,我们可以使用 threading 模块启动线程,该模块是 CPython 标准库的内置部分。这是怎么做的
import threadingdef hello: print "Hello threading!"my_thread = threading.Thread(target=hello) # target param reference the function hello# starting a threadmy_thread.start # prints 'Hello threading!'#Output Hello threading!现在我们了解了如何启动线程,自然而然的后续操作是学习如何在线程启动后停止它。
但是,这里有点令人失望:在 Python 中,您无法直接阻止线程执行。存在此限制是因为线程可能持有关键资源,例如文件句柄或数据库连接。在没有正确释放这些资源的情况下强行停止线程可能会导致资源泄漏、数据损坏或其他不可预知的行为。
也就是说,有一些方法可以正常地停止线程,我们将在下面讨论。
使用标志停止线程的常见方法是使用共享标志 (布尔变量) 。线程会定期检查此标志,并在该标志设置为 False 时退出。
import threadingimport time# Shared flag to control the threadstop_flag = Falsedef worker: while not stop_flag: print("Thread is running...") time.sleep(1) print("Thread stopped!")# Create and start the threadthread = threading.Thread(target=worker)thread.start# Let the thread run for 5 secondstime.sleep(5)# Set the stop flag to stop the threadstop_flag = True# Wait for the thread to finishthread.joinprint("Main program finished.")使用超时的联接您可以使用带有超时的 .join方法在一段时间后停止线程。
import threadingimport timedef worker: for i in range(10): print(f"Thread is running... {i}") time.sleep(1)# Create and start the threadthread = threading.Thread(target=worker)thread.start# Use join with a timeout to stop the thread after 5 secondsthread.join(timeout=5)if thread.is_alive: print("Thread is still running after timeout. Stopping the main program.")else: print("Thread completed within the timeout.")使用守护程序线程守护程序线程在主程序退出时自动终止。您可以通过在创建线程时传递 daemon = True将线程设置为守护程序。
import threadingimport timedef worker: for i in range(10): print(f"Thread is running... {i}") time.sleep(1)# Create and start the daemon threadthread = threading.Thread(target=worker, daemon=True)thread.start# Let the thread run for 5 secondstime.sleep(5)print("Main program finished. Daemon thread will stop automatically.")当您想在 python 中执行多线程时,您很可能会使用 threading 模块,因此最好使用此类中最常用的方法
运行 start 开始加入is_alivesetNamegetNameimport threadingimport time# Define a worker function for the threaddef worker: print(f"Thread '{threading.current_thread.getName}' is starting...") for i in range(5): print(f"Thread '{threading.current_thread.getName}' is running... {i}") time.sleep(1) print(f"Thread '{threading.current_thread.getName}' is finished.")# Create a threadthread = threading.Thread(target=worker)# Set the name of the threadthread.setName("MyWorkerThread")# Get the name of the threadprint(f"Thread name before starting: {thread.getName}")# Check if the thread is alive (before starting)print(f"Is thread alive before starting? {thread.is_alive}")# Start the threadprint("Starting the thread...")thread.start# Check if the thread is alive (after starting)print(f"Is thread alive after starting? {thread.is_alive}")# Wait for the thread to finish using joinprint("Main program is waiting for the thread to finish...")thread.join# Check if the thread is alive (after join)print(f"Is thread alive after join? {thread.is_alive}")# Demonstrate running the function in the current threadprint("Running the worker function in the main thread...")workerprint("Main program finished.")来源:自由坦荡的湖泊AI一点号