Python - Thread Priority

Trong Python, hiện tại độ ưu tiên của luồng không được hỗ trợ trực tiếp bởi mô-đun threading . Khác với Java, Python không hỗ trợ độ ưu tiên của luồng, nhóm luồng, hoặc một số cơ chế điều khiển luồng như hủy, dừng, tạm dừng, tiếp tục hoặc ngắt các luồng. Mặc dù các luồng Python được thiết kế đơn giản và dựa trên mô hình Java's threading một cách lỏng lẻo. Điều này là do Khóa Bộ thông dịch Toàn cầu (GIL) của Python, điều khiển các luồng Python.

Tuy nhiên, bạn có thể mô phỏng hành vi dựa trên ưu tiên bằng cách sử dụng các kỹ thuật như thời gian ngủ, logic lập lịch tùy chỉnh trong các luồng hoặc sử dụng mô-đun bổ sung quản lý các ưu tiên tác vụ.

Setting the Thread Priority Using Sleep()

Bạn có thể mô phỏng độ ưu tiên của luồng bằng cách giới thiệu độ trễ hoặc sử dụng các cơ chế khác để kiểm soát thứ tự thực thi của các luồng. Một cách phổ biến để mô phỏng độ ưu tiên của luồng là điều chỉnh thời gian ngủ của các luồng của bạn.

Các luồng có độ ưu tiên thấp sẽ ngủ lâu hơn, trong khi các luồng có độ ưu tiên cao sẽ ngủ ngắn hơn.

Example

Dưới đây là một ví dụ đơn giản để minh họa cách tùy chỉnh độ ưu tiên của các luồng bằng cách sử dụng độ trễ trong các luồng Python. Trong ví dụ này, Thread-2 hoàn thành trước Thread-1 vì nó có giá trị ưu tiên thấp hơn, dẫn đến thời gian ngủ ngắn hơn.

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

Khi thực thi chương trình trên, bạn sẽ nhận được các kết quả sau −

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

Trên hệ điều hành Windows, bạn có thể thao tác với độ ưu tiên của luồng bằng cách sử dụng mô-đun ctypes , đây là một trong những mô-đun chuẩn của Python được sử dụng để tương tác với API của Windows.

Example

Ví dụ này minh họa cách đặt mức độ ưu tiên của các luồng trong Python trên hệ thống Windows bằng cách sử dụng mô-đun ctypes .

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

Khi thực thi đoạn mã này trong trình thông dịch Python của bạn, bạn sẽ nhận được các kết quả sau −

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

Prioritizing Python Threads Using the Queue Module

Mô-đun queue trong thư viện chuẩn của Python rất hữu ích trong lập trình đa luồng khi thông tin phải được trao đổi một cách an toàn giữa nhiều luồng. Lớp Priority Queue trong mô-đun này thực hiện tất cả các ngữ nghĩa khóa cần thiết.

Với hàng đợi ưu tiên, các mục được giữ theo thứ tự (sử dụng mô-đun heapq ) và mục có giá trị thấp nhất được truy xuất trước.

Các đối tượng Queue có các phương thức sau để điều khiển Queue −

  • get() − Hàm get() loại bỏ và trả về một mục từ hàng đợi.

  • put() − Phương thức put thêm một mục vào hàng đợi.

  • qsize() − Hàm qsize() trả về số lượng mục hiện có trong hàng đợi.

  • empty() − Hàm empty( ) trả về True nếu hàng đợi rỗng; ngược lại, trả về False.

  • full() − phương thức full() trả về True nếu hàng đợi đầy; ngược lại, trả về False.

queue.PriorityQueue(maxsize=0)

Đây là Constructor cho một hàng đợi ưu tiên. maxsize là một số nguyên đặt giới hạn tối đa cho số lượng mục có thể được đặt trong hàng đợi. Nếu maxsize nhỏ hơn hoặc bằng không, kích thước hàng đợi là vô hạn.

Các mục có giá trị thấp nhất được truy xuất trước (mục có giá trị thấp nhất là mục sẽ được trả về bởi min(entries)). Một mẫu điển hình cho các mục là một tuple ở dạng -

(priority_number, data)

Example

Ví dụ này minh họa việc sử dụng lớp PriorityQueue trong mô-đun queue để quản lý độ ưu tiên tác vụ giữa hai luồng.

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

Khi thực thi, nó sẽ tạo ra đầu ra sau:

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