Python 简明教程
Python - Multithreading
在 Python 中,多线程允许你在单个进程内同时运行多个线程,这也被称为基于线程的并行性。这意味着一个程序可以同时执行多个任务,从而提高其效率和响应能力。
In Python, multithreading allows you to run multiple threads concurrently within a single process, which is also known as thread-based parallelism. This means a program can perform multiple tasks at the same time, enhancing its efficiency and responsiveness.
Python 中的多线程对于多个 I/O 绑定操作特别有用,而不是对于需要大量计算的任务。
Multithreading in Python is especially useful for multiple I/O-bound operations, rather than for tasks that require heavy computation.
通常,一个计算机程序从头到尾顺序执行指令。而多线程将主任务分解为多个子任务,并以重叠的方式执行它们。
Generally, a computer program sequentially executes the instructions, from start to the end. Whereas, Multithreading divides the main task into more than one sub-task and executes them in an overlapping manner.
Comparison with Processes
操作系统能够同时处理多个进程。它为每个进程分配一个单独的内存空间,以便一个进程无法访问或写入另一个进程的空间。
An operating system is capable of handling multiple processes concurrently. It allocates a separate memory space to each process so that one process cannot access or write anything in other’s space.
另一方面,一个线程可以被视为一个程序中共享分配给它的内存空间的轻量级子进程,从而促进更轻松的通信和数据共享。由于它们轻巧且不需要太多内存开销;因此它们比进程便宜。
On the other hand, a thread can be considered a lightweight sub-process in a single program that shares the memory space allocated to it, facilitating easier communication and data sharing. As they are lightweight and do not require much memory overhead; they are cheaper than processes.
一个进程总是从一个线程(主线程)开始。根据需要,可以启动一个新线程并委派子任务给它。现在这两个线程正在以重叠的方式工作。当分配给辅助线程的任务完成后,它会与主线程合并。
A process always starts with a single thread (main thread). As and when required, a new thread can be started and sub task is delegated to it. Now the two threads are working in an overlapping manner. When the task assigned to the secondary thread is over, it merges with the main thread.
一个线程有开始、执行序列和结尾。它有一个指令指针,用来跟踪它当前在其上下文中运行的位置。
A thread has a beginning, an execution sequence, and a conclusion. It has an instruction pointer that keeps track of where it is currently running within its context.
-
It can be pre-empted (interrupted)
-
It can temporarily be put on hold (also known as sleeping) while other threads are running - this is called yielding.
Thread Handling Modules in Python
Python 的标准库提供两个用于管理线程的主要模块: _thread 和 threading 。
Python’s standard library provides two main modules for managing threads: _thread and threading.
The _thread Module
_thread 模块(也被称为低级线程模块)从 Python 2 版本开始就成为 Python 标准库的一部分。它为线程管理提供基本 API,支持在共享的全局数据空间中并发执行线程。该模块包括用于同步的简单锁(互斥)。
The _thread module, also known as the low-level thread module, has been a part of Python’s standard library since version 2. It offers a basic API for thread management, supporting concurrent execution of threads within a shared global data space. The module includes simple locks (mutexes) for synchronization purposes.
The threading Module
在 Python 2.4 中引入的 threading 模块建立在 _thread 的基础上,提供更高级且更全面的线程 API。它提供用于管理线程的强大工具,更便于在 Python 应用程序中使用线程。
The threading module, introduced in Python 2.4, builds upon _thread to provide a higher-level and more comprehensive threading API. It offers powerful tools for managing threads, making it easier to work with threads in Python applications.
Key Features of the threading Module
Key Features of the threading Module
threading 模块显示了 thread 模块的所有方法,并提供一些附加方法——
The threading module exposes all the methods of the thread module and provides some additional methods −
-
threading.activeCount() − Returns the number of thread objects that are active.
-
threading.currentThread() − Returns the number of thread objects in the caller’s thread control.
-
threading.enumerate() − Returns a list of all thread objects that are currently active.
除了方法之外,threading 模块还有实现线程的 Thread 类。Thread 类提供的方法如下——
In addition to the methods, the threading module has the Thread class that implements threading. The methods provided by the Thread class are as follows −
-
run() − The run() method is the entry point for a thread.
-
start() − The start() method starts a thread by calling the run method.
-
join([time]) − The join() waits for threads to terminate.
-
isAlive() − The isAlive() method checks whether a thread is still executing.
-
getName() − The getName() method returns the name of a thread.
-
setName() − The setName() method sets the name of a thread.
Starting a New Thread
要在 Python 中创建和启动新线程,可以使用低级的 _thread 模块或高级的 threading 模块。由于 threading 模块具有更多功能且易于使用,因此通常建议使用它。在下面,你可以看到两种方法。
To create and start a new thread in Python, you can use either the low-level _thread module or the higher-level threading module. The threading module is generally recommended due to its additional features and ease of use. Below, you can see both approaches.
Starting a New Thread Using the _thread Module
_thread 模块的 start_new_thread() 方法提供了创建和启动新线程的基本方式。该方法提供了在 Linux 和 Windows 中创建新线程的快速且高效的方式。以下是该方法的语法——
The start_new_thread() method of the _thread module provides a basic way to create and start new threads. This method provides a fast and efficient way to create new threads in both Linux and Windows. Following is the syntax of the method −
thread.start_new_thread(function, args[, kwargs] )
此方法调用立即返回,新线程开始使用给定参数执行指定函数。当函数返回时,线程终止。
This method call returns immediately, and the new thread starts executing the specified function with the given arguments. When the function returns, the thread terminates.
Example
此示例演示如何使用 _thread 模块创建和运行线程。每个线程使用不同的参数运行 print_name 函数。time.sleep(0.5) 调用确保主程序在退出前等待线程完成其执行。
This example demonstrates how to use the _thread module to create and run threads. Each thread runs the print_name function with different arguments. The time.sleep(0.5) call ensures that the main program waits for the threads to complete their execution before exiting.
import _thread
import time
def print_name(name, *arg):
print(name, *arg)
name="Tutorialspoint..."
_thread.start_new_thread(print_name, (name, 1))
_thread.start_new_thread(print_name, (name, 1, 2))
time.sleep(0.5)
执行上述代码后,将生成以下结果 −
When the above code is executed, it produces the following result −
Tutorialspoint... 1
Tutorialspoint... 1 2
虽然它对于低级别线程化非常有效,但与 threading 模块相比,_thread 模块的功能有限,后者提供了更多功能和更高级别的线程管理。
Although it is very effective for low-level threading, but the _thread module is limited compared to the threading module, which offers more features and higher-level thread management.
Starting a New Thread Using the Threading Module
threading 模块提供 Thread 类,用于创建和管理线程。
The threading module provides the Thread class, which is used to create and manage threads.
以下步骤使用线程模块启动新线程:
Here are a few steps to start a new thread using the threading module −
-
Create a function that you want the thread to execute.
-
Then create a Thread object using the Thread class by passing the target function and its arguments.
-
Call the start method on the Thread object to begin execution.
-
Optionally, call the join method to wait for the thread to complete before proceeding.
Example
下面的示例演示如何使用 threading 模块创建并启动线程。它运行一个 print_name 函数,该函数打印名称以及一些参数。此示例创建两个线程,使用 start() 方法启动它们,并使用 join 方法等待它们完成。
The following example demonstrates how to create and start threads using the threading module. It runs a function print_name that prints a name along with some arguments. This example creates two threads, starts them using the start() method, and waits for them to complete using the join method.
import threading
import time
def print_name(name, *args):
print(name, *args)
name = "Tutorialspoint..."
# Create and start threads
thread1 = threading.Thread(target=print_name, args=(name, 1))
thread2 = threading.Thread(target=print_name, args=(name, 1, 2))
thread1.start()
thread2.start()
# Wait for threads to complete
thread1.join()
thread2.join()
print("Threads are finished...exiting")
执行上述代码后,将生成以下结果 −
When the above code is executed, it produces the following result −
Tutorialspoint... 1
Tutorialspoint... 1 2
Threads are finished...exiting
Synchronizing Threads
Python 提供的线程模块包括一个易于实现的锁机制,允许同步线程。通过调用 Lock() 方法创建一个新锁,该方法返回新锁。
The threading module provided with Python includes a simple-to-implement locking mechanism that allows you to synchronize threads. A new lock is created by calling the Lock() method, which returns the new lock.
新锁对象的 acquire(blocking) 方法用于强制线程同步运行。可选的阻塞参数使您可以控制线程是否等待获取锁。
The acquire(blocking) method of the new lock object is used to force threads to run synchronously. The optional blocking parameter enables you to control whether the thread waits to acquire the lock.
如果将阻塞设置 0,则如果无法获取锁,则线程立即返回 0 值,如果获取锁,则返回 1。如果阻塞设置 1,则线程将阻塞并等待释放锁。
If blocking is set to 0, the thread returns immediately with a 0 value if the lock cannot be acquired and with a 1 if the lock was acquired. If blocking is set to 1, the thread blocks and wait for the lock to be released.
新锁对象的 release() 方法用于不再需要时释放锁。
The release() method of the new lock object is used to release the lock when it is no longer required.
Example
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("Starting " + self.name)
# Get lock to synchronize threads
threadLock.acquire()
print_time(self.name, self.counter, 3)
# Free lock to release next thread
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
threadLock = threading.Lock()
threads = []
# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print ("Exiting Main Thread")
执行上述代码后,将生成以下结果 −
When the above code is executed, it produces the following result −
Starting Thread-1
Starting Thread-2
Thread-1: Thu Mar 21 09:11:28 2013
Thread-1: Thu Mar 21 09:11:29 2013
Thread-1: Thu Mar 21 09:11:30 2013
Thread-2: Thu Mar 21 09:11:32 2013
Thread-2: Thu Mar 21 09:11:34 2013
Thread-2: Thu Mar 21 09:11:36 2013
Exiting Main Thread
Multithreaded Priority Queue
队列模块允许您创建一个可以容纳一定数量项的新队列对象。有以下方法来控制队列:
The Queue module allows you to create a new queue object that can hold a specific number of items. There are following methods to control the Queue −
-
get() − The get() removes and returns an item from the queue.
-
put() − The put adds item to a queue.
-
qsize() − The qsize() returns the number of items that are currently in the queue.
-
empty() − The empty( ) returns True if queue is empty; otherwise, False.
-
full() − the full() returns True if queue is full; otherwise, False.
Example
import queue
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print ("Starting " + self.name)
process_data(self.name, self.q)
print ("Exiting " + self.name)
def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print ("%s processing %s" % (threadName, data))
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1
# Create new threads
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# Fill the queue
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# Wait for queue to empty
while not workQueue.empty():
pass
# Notify threads it's time to exit
exitFlag = 1
# Wait for all threads to complete
for t in threads:
t.join()
print ("Exiting Main Thread")
执行上述代码后,将生成以下结果 −
When the above code is executed, it produces the following result −
Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-1 processing One
Thread-2 processing Two
Thread-3 processing Three
Thread-1 processing Four
Thread-2 processing Five
Exiting Thread-3
Exiting Thread-1
Exiting Thread-2
Exiting Main Thread