Python 简明教程

Python - Thread Priority

在 Python 中,目前 threading 模块并不直接支持线程优先权。与 Java 不同,Python 不支持线程优先权、线程组或某些线程控制机制(例如销毁、停止、挂起、恢复或中断线程)。

尽管 Python 线程被设计得简单并且基本上基于 Java’s threading 模型。这是因为 Python 的全局解释器锁 (GIL),它可以管理 Python 线程。

但是,您可以使用诸如睡眠持续时间、线程内的自定义调度逻辑或用于管理任务优先权的其他模块之类的技术来模拟基于优先权的行为。

Setting the Thread Priority Using Sleep()

您可以通过引入延迟或使用其他机制控制线程执行顺序来模拟线程优先权。模拟线程优先权的一种常见方法是调整线程的睡眠持续时间。

优先权较低的线程睡眠时间较长,而优先权较高的线程睡眠时间较短。

Example

这是一个简单的示例,演示如何使用 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")

# Creating threads with different priorities
t1 = DummyThread(name='Thread-1', priority=4)
t2 = DummyThread(name='Thread-2', priority=1)

# Starting the threads
t1.start()
t2.start()

# Waiting for both threads to complete
t1.join()
t2.join()

print('All Threads are executed')

Output

通过执行以上的程序,你会得到以下结果:

Thread-2 thread with priority 1 is running
Thread-1 thread with priority 4 is running
All Threads are executed

Adjusting Python Thread Priority on Windows

在 Windows 操作系统上,您可以使用 ctypes 模块操纵线程优先权,这是用于与 Windows API 交互的 Python 标准模块之一。

Example

此示例演示了如何在 Windows 系统上使用 ctypes 模块手动设置 Python 中线程的优先权。

import threading
import ctypes
import time

# Constants for Windows API
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

# Create an event to synchronize thread start
start_event = threading.Event()

# Create threads
thread_normal = MyThread(start_event, name='normal', iterations=4)
thread_high = MyThread(start_event, name='high', iterations=4)

# Start the threads
thread_normal.start()
thread_high.start()

# Adjusting priority of 'high' thread
thread_high.set_priority(PRIORITIZE_THE_THREAD)

# Trigger thread execution
start_event.set()

Output

在 Python 解释器中执行此代码时,您将获得以下结果 -

high running
normal running
high running
normal running
high running
normal running
high running
normal running

Prioritizing Python Threads Using the Queue Module

当必须在多个线程之间安全地交换信息时,Python 标准库中的 queue 模块在多线程编程中非常有用。此模块中的优先级队列类实现了所有必需的锁定语义。

对于优先级队列,条目是有序的(使用 heapq 模块),第一个检索到的条目是值最低的条目。

Queue 对象具备以下方法来控制队列−

  1. get() − get() 从队列中删除并返回一个项。

  2. put() − put 向队列中添加项。

  3. qsize() − qsize() 返回队列中当前的项数。

  4. empty() − empty( ) 如果队列为空,则返回 True;否则返回 False。

  5. full() −full() 如果队列已满则返回 True;否则,返回 False。

queue.PriorityQueue(maxsize=0)

这是用于优先级队列的构造函数。maxsize 为一个整数,用于设定可存入队列的条目数量上限。如果 maxsize 等于或小于零,则队列大小为无限。

首先检索到值最低的条目(值最低的条目是 min(entries) 将返回的条目)。条目的典型模式是一种元组,形式如下 −

(priority_number, data)

Example

此示例演示在 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):

      # create item with priority
      value = random()
      priority = randint(0, 5)
      item = (priority, value)
      queue.put(item)
   # wait for all items to be processed
   queue.join()

   queue.put(None)
   print('Producer: Done')

def consumer(queue):
   print('Consumer: Running')

   while True:

      # get a unit of work
      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()

Output

执行时,它将生成以下输出 −

Producer: Running
Consumer: Running
(0, 0.15332707626852804)
(2, 0.4730737391435892)
(2, 0.8679231358257962)
(3, 0.051924220435665025)
(4, 0.23945882716108446)
Producer: Done
Consumer: Done