我想創建一個程式,它每隔一段時間執行一些任務,比如每 4 秒,但這應該使用多個執行緒來完成,這些執行緒輪流完成,每個執行緒執行一個任務,然后允許另一個執行下一個任務。
如果每 4 秒列印一次是我想要執行的任務,那么事件順序可能如下所示。
Thread 1 printed at 0 seconds
Thread 2 printed at 4 seconds
Thread 3 printed at 8 seconds
Thread 1 printed at 12 seconds
...
我通過存盤執行緒 ID 的佇列來解決這個問題,并將佇列的第一個元素視為應該執行任務的下一個執行緒的 ID。當一個執行緒執行任務時,佇列會旋轉,以便另一個執行緒接下來執行該任務。自上次任務完成以來的時間是在每個執行緒的每次迭代中計算的,用于確定執行緒是否應該執行任務(以及輪到當前執行緒)。
這是代碼
from threading import Thread, Lock
import threading
from collections import deque
from datetime import datetime
import time
mutex = Lock()
print_interval = 4.0
thread_queue = deque([])
running = True
def print_thread():
last_print_time = datetime.now()
while running:
mutex.acquire()
delta_time = (datetime.now() - last_print_time).total_seconds()
if delta_time >= print_interval and threading.get_ident() == thread_queue[0]:
last_print_time = datetime.now()
thread_queue.rotate(1)
print('Thread {} printing at time {}'.format(threading.get_ident(), datetime.now().time()), flush=True)
mutex.release()
threads = []
for i in range(4):
thread = Thread(target = print_thread)
thread.start()
thread_queue.append(thread.ident)
time.sleep(10)
running = False
for thread in threads:
thread.join()
這是一個輸出示例。
Thread 29548 printing at time 17:11:50.662538
Thread 34616 printing at time 17:11:50.683628
Thread 35900 printing at time 17:11:50.683628
Thread 27924 printing at time 17:11:50.683628
Thread 29548 printing at time 17:11:54.667393
Thread 34616 printing at time 17:11:54.683969
Thread 35900 printing at time 17:11:54.683969
而不是執行緒等待正確的時間過去,由于某種原因,delta_time 計算在背景關系切換時爆炸并且執行緒立即執行任務,僅在所有執行緒完成任務時才暫停。我的邏輯在這里正確嗎?我不確定出了什么問題。
謝謝。
編輯:我將解釋我認為 print_thread 應該如何分步運行并盡量弄清楚它。假設我們有 2 個執行緒,ID 分別為 1 和 2,執行緒佇列看起來像 [1,2](執行緒 1 先行)
Thread 1 acquires the lock
delta_time is < 4
conditional fails to execute
Thread 1 releases the lock
Thread 2 acquires the lock
delta_time is < 4
conditional fails to execute
Thread 2 releases the lock
This goes on for about 4 seconds...
Thread 1 acquires the lock
delta_time is 4.1
conditional is true because delta_time is >= 4 and this thread is at the front of the queue
last_print_time = current time
rotate queue (thread 2 will be next)
Thread 1 releases the lock
Thread 2 acquires the lock
delta_time is 0.01
conditional fails because not enough time has passed
Thread 2 releases the lock
抱歉,如果這很冗長,但這基本上是我所期望的流程以及為什么執行緒應該按順序執行,而不是一次執行。
uj5u.com熱心網友回復:
至于我的主要問題是每個執行緒都使用自己的私有執行緒last_print_time
,并且它不會last_print_time
在其他執行緒中重置。
你將不得不使用global last_print_time
帶有全域變數的完整代碼。
我設定更長的時間sleep()
來查看結果。
from threading import Thread, Lock
import threading
from collections import deque
from datetime import datetime
import time
mutex = Lock()
print_interval = 4.0
thread_queue = deque([])
running = True
last_print_time = datetime.now()
def print_thread():
global last_print_time
while running:
mutex.acquire()
delta_time = (datetime.now() - last_print_time).total_seconds()
if delta_time >= print_interval and threading.get_ident() == thread_queue[0]:
last_print_time = datetime.now()
thread_queue.rotate(1)
print('Thread {} printing at time {}'.format(threading.get_ident(), datetime.now().time()), flush=True)
mutex.release()
threads = []
for i in range(4):
thread = Thread(target = print_thread)
thread.start()
thread_queue.append(thread.ident)
time.sleep(30)
running = False
for thread in threads:
thread.join()
結果:
Thread 140276746778368 printing at time 19:40:20.012389
Thread 140276517566208 printing at time 19:40:24.015615
Thread 140276729992960 printing at time 19:40:28.021712
Thread 140276738385664 printing at time 19:40:32.037404
Thread 140276746778368 printing at time 19:40:36.038693
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/470126.html
上一篇:在此同步不起作用。為什么?我已經同步了所有方法。任何人都可以告訴并提供相同的解決方案嗎?
下一篇:至少一個完成后如何啟動執行緒