一、定义线程
Python中可以使用 threading 模块来创建和管理线程。其中,Thread 类是最常用的线程类,可以通过继承该类来自定义线程对象,也可以直接调用 threading.Thread(target=func) 方法来创建线程对象。以下是一个简单的创建线程的示例:
import threading
def hello():
print("Hello, world!")
t = threading.Thread(target=hello) # 创建线程对象
t.start() # 启动线程
在上述示例中,我们定义了一个名为 hello() 的函数,里面只有一条输出语句。然后,我们通过 threading.Thread(target=hello)
方法来创建了一个线程对象 t。最后,通过 t.start()
方法来启动线程。该程序在执行时会同时输出 "Hello, world!" 和 "MainThread exiting..." 两条语句,因为新线程的执行速度远远超过主线程的退出速度。
二、获取线程对象
在 Python 中,每个线程对象都有一个唯一的标识符(Thread ID),可以通过线程对象的 ident
属性来获取。以下是一个获取线程对象的示例:
import threading
def hello():
print("Hello, world!")
t = threading.Thread(target=hello)
t.start()
print("Main thread ID is", threading.current_thread().ident)
print("Child thread ID is", t.ident)
在上述示例中,我们创建了一个名为 t 的线程对象,并启动了该线程。然后,我们通过 threading.current_thread() 方法来获取当前线程对象(主线程对象),并输出它的标识符。同时,我们也输出了子线程对象的标识符。
三、线程标识符映射表
在 Python 中,所有线程对象的标识符都存储在 threading._active 虚拟变量中,它是一个字典(dict),键为线程 ID,值为对应的线程对象。以下是一个输出线程标识符映射表的示例:
import threading
def hello():
print("Hello, world!")
t = threading.Thread(target=hello)
t.start()
for k, v in threading._active.items():
print("{}: {}".format(k, v))
在上述示例中,我们创建了一个名为 t 的线程对象,并启动了该线程。然后,我们通过遍历 threading._active.items() 方法来输出所有线程对象的标识符和值。
四、找到线程对象
在 Python 中,我们可以通过线程对象的标识符来查找线程对象。以下是一个查找线程对象的示例:
import threading
def hello():
print("Hello, world!")
t = threading.Thread(target=hello)
t.start()
thread_id = t.ident
for k, v in threading._active.items():
if k == thread_id:
print("Find the thread object, ID is", k)
print("Thread object is", v)
break
在上述示例中,我们创建了一个名为 t 的线程对象,并启动了该线程。然后,我们通过 t.ident 属性来获取线程对象的标识符,并保存到 thread_id 变量中。接着,我们通过遍历 threading._active.items() 方法来查找线程对象。找到线程对象后,我们输出了线程对象的标识符和值。
五、销毁线程对象
在 Python 中,我们可以使用 threading.Thread 类的 join() 方法来等待线程执行完毕。同时,我们可以使用 threading._cleanup() 方法来销毁所有已经终止的线程对象。以下是一个销毁线程对象的示例:
import threading
import time
def hello():
time.sleep(2)
print("Hello, world!")
t = threading.Thread(target=hello)
t.start()
t.join()
threading._cleanup()
print("All threads terminated.")
在上述示例中,我们创建了一个名为 t 的线程对象,并启动了该线程。然后,我们通过 t.join() 方法来等待线程执行完毕。最后,我们使用 threading._cleanup() 方法来销毁所有已经终止的线程对象。在程序执行完毕后,我们输出了一条 "All threads terminated." 的信息。
六、示例说明
线程池通常用于一次性创建大量的线程,以便执行一组相似的任务。使用线程池可以提高程序的效率,减少线程创建和销毁的开销。以下是一个使用线程池执行任务的示例:
import threading
from concurrent.futures import ThreadPoolExecutor
def calculate_square(x):
result = x * x
print("{} squared is {}".format(x, result))
return result
if __name__ == '__main__':
with ThreadPoolExecutor(max_workers=3) as executor:
future1 = executor.submit(calculate_square, 5)
future2 = executor.submit(calculate_square, 10)
future3 = executor.submit(calculate_square, 15)
在上述示例中,我们定义了一个名为 calculate_square() 的函数,用于计算给定数字的平方,并输出计算结果。然后,我们使用 ThreadPoolExecutor 类来创建一个最多包含 3 个线程的线程池。接着,我们使用 executor.submit() 方法将任务提交给线程池执行。该程序在执行时会输出以下信息:
5 squared is 25
15 squared is 225
10 squared is 100
说明:我们使用了 Future 对象来追踪任务的状态和结果。调用 executor.submit() 方法时,该方法会返回一个 Future 对象,我们可以通过该对象的 result() 方法来获取任务的计算结果。
在 Python 中,我们可以通过将线程对象的 daemon 属性设置为 True,来将线程定义为守护线程。守护线程会在主线程结束时自动退出,无需等待其它线程完成任务。以下是一个定义守护线程的示例:
import threading
import time
def hello():
while True:
print("Hello, world!")
time.sleep(1)
t = threading.Thread(target=hello)
t.daemon = True
t.start()
print("Main thread exiting...")
在上述示例中,我们定义了一个死循环的 hello() 函数,用于输出 "Hello, world!"。然后,我们创建了一个名为 t 的线程对象,并将它设置为守护线程。接着,我们启动了该线程,并输出了一条 "Main thread exiting..." 的信息。程序在执行时只会输出 "Hello, world!" 和 "Main thread exiting..." 两条信息,因为守护线程会在主线程退出时自动退出。
说明:程序的执行速度很快,需要手动结束程序才能停止守护线程的输出。