我有一个Python程序,其中包括一个主线程和两个或更多其他线程(也许数量不重要)。我希望让主线程休眠直到其中一个其他线程完成。使用轮询很容易实现(通过调用t.join(1)并等待每个线程t一秒钟)。
是否可以在不进行轮询的情况下完成?
SOMETHING_LIKE_JOIN(1, [t1, t2])
其中t1和t2是线程.Thread对象。该调用必须执行以下操作:休眠1秒钟,但一旦t1或t2中的一个完成,就立即唤醒。与POSIX select(2)调用具有两个文件描述符非常相似。
我有一个Python程序,其中包括一个主线程和两个或更多其他线程(也许数量不重要)。我希望让主线程休眠直到其中一个其他线程完成。使用轮询很容易实现(通过调用t.join(1)并等待每个线程t一秒钟)。
是否可以在不进行轮询的情况下完成?
SOMETHING_LIKE_JOIN(1, [t1, t2])
其中t1和t2是线程.Thread对象。该调用必须执行以下操作:休眠1秒钟,但一旦t1或t2中的一个完成,就立即唤醒。与POSIX select(2)调用具有两个文件描述符非常相似。
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(2) # Two workers
for res in pool.imap_unordered(some_func, list_of_func_args):
# res is whatever some_func returned
会在任务完成时立即返回结果,而不管哪个任务先完成。
from threading import Thread, Condition, Lock
from time import sleep
from random import random
_lock = Lock()
def run(idx, condition):
sleep(random() * 3)
print('thread_%d is waiting for notifying main thread.' % idx)
_lock.acquire()
with condition:
print('thread_%d notifies main thread.' % idx)
condition.notify()
def is_working(thread_list):
for t in thread_list:
if t.is_alive():
return True
return False
def main():
condition = Condition(Lock())
thread_list = [Thread(target=run, kwargs={'idx': i, 'condition': condition}) for i in range(10)]
with condition:
with _lock:
for t in thread_list:
t.start()
while is_working(thread_list):
_lock.release()
if condition.wait(timeout=1):
print('do something')
sleep(1) # <-- Main thread is doing something.
else:
print('timeout')
for t in thread_list:
t.join()
if __name__ == '__main__':
main()
我刚刚意识到之前的示例中存在竞争条件。我添加了一个全局_lock来确保该条件永远不会通知主线程,直到主线程开始等待。我不喜欢它的工作方式,但我还没有找到更好的解决方案...
with
语句。这样可以避免忘记释放锁的风险,并防止异常绕过release
。此外,这种方式更加简洁,run
函数的最后四行代码可以改为:with condition:
、condition.notify()
、print('thread_%d' % idx)
。 - ShadowRangerimport threading
import time, random
#THREAD CLASS#
class Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
self.state = False
#START THREAD (THE RUN METHODE)#
self.start()
#THAT IS WHAT THE THREAD ACTUALLY DOES#
def run(self):
#THREAD SLEEPS FOR A RANDOM TIME RANGE#
time.sleep(random.randrange(5, 10))
#AFTERWARDS IS HAS FINISHED (STORE IN VARIABLE)#
self.state = True
#RETURNS THE STATE#
def getState(self):
return self.state
#10 SEPERATE THREADS#
threads = []
for i in range(10):
threads.append(Thread())
#MAIN THREAD#
while True:
#RUN THROUGH ALL THREADS AND CHECK FOR ITS STATE#
for i in range(len(threads)):
if threads[i].getState():
print "WAITING IS OVER: THREAD ", i
#SLEEPS ONE SECOND#
time.sleep(1)