目前 Python 的 threading 模块并不直接支持线程优先级。与 Java 不同,Python 不支持线程优先级、线程组或某些线程控制机制如销毁、停止、暂停、恢复或中断线程。
这是因为 Python 的线程设计较为简单,并且基于 Java 的线程模型进行了简化。Python 的全局解释器锁(GIL)管理着 Python 的线程,使得线程间的 CPU 时间分配不是根据优先级而是按照某种公平的方式进行。
然而,你可以使用一些技术来模拟基于优先级的行为,比如使用睡眠持续时间、在线程内部实现自定义调度逻辑或使用管理任务优先级的附加模块。
使用 sleep() 设置线程优先级
你可以通过引入延迟或其他机制来控制线程的执行顺序,以此来模拟线程优先级。一种常见的模拟线程优先级的方法是调整线程的睡眠时间长度。
具有较低优先级的线程会睡得更久,而具有较高优先级的线程则会睡得更短。
示例
下面是一个简单的示例,展示如何使用 Python 线程中的延迟来自定义线程优先级。在这个例子中,Thread-2 先于 Thread-1 完成,因为它有更低的优先级值,导致更短的睡眠时间。
import threading
import time
class DummyThread(threading.Thread):
def __init__(self, name, priority):
threading.Thread.__init__(self)
self.name = name
self.priority = priority
def run(self):
name = self.name
time.sleep(1.0 * self.priority)
print(f"{name} thread with priority {self.priority} is running")
t1 = DummyThread(name='Thread-1', priority=4)
t2 = DummyThread(name='Thread-2', priority=1)
t1.start()
t2.start()
t1.join()
t2.join()
print('All Threads are executed')
输出:
Thread-2 thread with priority 1 is running
Thread-1 thread with priority 4 is running
All Threads are executed
在 Windows 上调整 Python 线程优先级
在 Windows 操作系统上,你可以使用 ctypes 模块来操控线程优先级。ctypes 是 Python 的标准模块之一,用于与 Windows API 进行交互。
示例
下面的示例演示了如何在 Windows 系统上使用 ctypes 模块手动设置 Python 线程的优先级。
import threading
import ctypes
import time
w32 = ctypes.windll.kernel32
SET_THREAD = 0x20
PRIORITIZE_THE_THREAD = 1
class MyThread(threading.Thread):
def __init__(self, start_event, name, iterations):
super().__init__()
self.start_event = start_event
self.thread_id = None
self.iterations = iterations
self.name = name
def set_priority(self, priority):
if not self.is_alive():
print('Cannot set priority for a non-active thread')
return
thread_handle = w32.OpenThread(SET_THREAD, False, self.thread_id)
success = w32.SetThreadPriority(thread_handle, priority)
w32.CloseHandle(thread_handle)
if not success:
print('Failed to set thread priority:', w32.GetLastError())
def run(self):
self.thread_id = w32.GetCurrentThreadId()
self.start_event.wait()
while self.iterations:
print(f"{self.name} running")
start_time = time.time()
while time.time() - start_time < 1:
pass
self.iterations -= 1
start_event = threading.Event()
thread_normal = MyThread(start_event, name='normal', iterations=4)
thread_high = MyThread(start_event, name='high', iterations=4)
thread_normal.start()
thread_high.start()
thread_high.set_priority(PRIORITIZE_THE_THREAD)
start_event.set()
输出:
high running
normal running
high running
normal running
high running
normal running
high running
normal running
使用 queue 模块优先化 Python 线程
Python 标准库中的 queue 模块在多线程编程中有用,当信息需要在多个线程之间安全交换时。此模块中的 PriorityQueue 类实现了所需的所有锁定语义。
使用优先队列时,条目保持排序(使用 heapq 模块),并且首先检索最低值的条目。
队列对象具有以下方法来控制队列:
-
-
-
-
empty()
- 如果队列为空则返回 True;否则返回 False。
-
full()
- 如果队列已满则返回 True;否则返回 False。
queue.PriorityQueue(maxsize=0)
是优先队列的构造函数。maxsize 是一个设置队列可以放置的最大项数的整数。如果 maxsize 小于等于零,则队列大小是无限的。
条目的典型形式是一个元组:
(priority_number, data)
示例
下面的示例演示了如何使用 queue 模块中的 PriorityQueue 类来管理两个线程之间的任务优先级。
from time import sleep
from random import random, randint
from threading import Thread
from queue import PriorityQueue
queue = PriorityQueue()
def producer(queue):
print('Producer: Running')
for i in range(5):
value = random()
priority = randint(0, 5)
item = (priority, value)
queue.put(item)
queue.join()
queue.put(None)
print('Producer: Done')
def consumer(queue):
print('Consumer: Running')
while True:
item = queue.get()
if item is None:
break
sleep(item[1])
print(item)
queue.task_done()
print('Consumer: Done')
producer = Thread(target=producer, args=(queue,))
producer.start()
consumer = Thread(target=consumer, args=(queue,))
consumer.start()
producer.join()
consumer.join()
输出:
Producer: Running
Consumer: Running
(0, 0.15332707626852804)
(2, 0.4730737391435892)
(2, 0.8679231358257962)
(3, 0.051924220435665025)
(4, 0.23945882716108446)
Producer: Done
Consumer: Done