Python - 執行緒優先順序



在 Python 中,目前 **threading** 模組不直接支援執行緒優先順序。與 Java 不同,Python 不支援執行緒優先順序、執行緒組或某些執行緒控制機制,例如銷燬、停止、掛起、恢復或中斷執行緒。

儘管 Python 執行緒設計簡單,並且鬆散地基於 Java 的執行緒 模型。這是由於 Python 的全域性直譯器鎖 (GIL),它管理著 Python 執行緒。

但是,您可以使用諸如睡眠時長、執行緒內的自定義排程邏輯或使用管理任務優先順序的附加模組等技術來模擬基於優先順序的行為。

使用 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")

# 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')

輸出

執行上述程式後,您將獲得以下結果:

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

在 Windows 上調整 Python 執行緒優先順序

在 Windows 作業系統上,您可以使用 **ctypes** 模組來操作執行緒優先順序,這是 Python 的標準模組之一,用於與 Windows API 互動。

示例

此示例演示瞭如何在 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()

輸出

在 Python 直譯器中執行此程式碼時,您將獲得以下結果:

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

使用 Queue 模組優先處理 Python 執行緒

Python 標準庫中的 **queue** 模組在多執行緒程式設計中非常有用,此時必須線上程之間安全地交換資訊。此模組中的 Priority Queue 類實現了所有必需的鎖定語義。

使用優先順序佇列,條目保持排序(使用 **heapq** 模組),並且首先檢索值最低的條目。

Queue 物件具有以下方法來控制佇列:

  • **get()** - get() 從佇列中移除並返回一個專案。

  • **put()** - put() 將專案新增到佇列中。

  • **qsize()** - qsize() 返回當前在佇列中的專案數量。

  • **empty()** - empty() 如果佇列為空,則返回 True;否則返回 False。

  • **full()** - full() 如果佇列已滿,則返回 True;否則返回 False。

queue.PriorityQueue(maxsize=0)

這是優先順序佇列的建構函式。maxsize 是一個整數,它設定可以放入佇列中的專案的數量上限。如果 maxsize 小於或等於零,則佇列大小無限。

值最低的條目首先被檢索(值最低的條目是 min(entries) 將返回的條目)。條目的典型模式是以下形式的元組:

(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):

      # 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()

輸出

執行後,它將產生以下輸出:

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