Python:在while循环中使用join()的线程
我希望我的while循环在for循环中创建的所有线程最多只阻塞5秒钟。但是,下面的代码会让线程一个接一个地阻塞。请问我该怎么做才能实现我的目标呢?谢谢。
threads = []
while True:
for 3:
newThread = threading.Thread(..)
threads.append(newThread)
newThread.start()
newThread.join(5)
3 个回答
0
你是不是想每隔5秒钟启动一个新线程,但如果已经在运行的线程结束了,你希望能更早地启动一个新线程?如果是这样的话,你可以使用一个叫做 threading.Event
的东西来通知你某个工作线程结束了,然后用 event.wait(timeout)
来最多等待5秒钟,看看有没有这个通知:
import threading
import time
import logging
logger=logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s: %(message)s',
datefmt='%H:%M:%S')
def foo_event(n,e):
time.sleep(n)
name=threading.current_thread().name
logger.info('{n}: setting event'.format(n=name))
e.set()
def main():
e=threading.Event()
threads=[]
N=5
for i in range(3):
t=threading.Thread(target=foo_event,args=(N+1,e,),name='worker-{i}'.format(i=i))
threads.append(t)
t.daemon=True
t.start()
logger.info('entering wait')
e.wait(N)
logger.info('exit wait')
e.clear()
main()
这样就可以实现了
05:06:34: entering wait
05:06:39: exit wait <-- Wait 5 seconds
05:06:39: entering wait
05:06:40: worker-0: setting event
05:06:40: exit wait <-- Wait <5 seconds
05:06:40: entering wait
05:06:45: worker-1: setting event
05:06:45: exit wait <-- Wait 5 seconds
2
一种做法是先启动所有的线程,然后遍历数组并把它们合并。不过,我想这样的话,还是会等到总共5乘以线程数量的秒数。另一种方法是可以再创建一个额外的线程,这个线程就一直等着你的其他线程完成。然后在你的主线程中,你只需要等这个额外的线程5秒钟就可以了。
3
你需要使用条件变量(在Python中是threading.Condition
)。它的作用是让你等待某个条件变为真。在你的情况下,这个条件是所有线程都完成工作或者超时
。下面的代码创建了十个线程,并等待它们在5秒内完成。详细的日志会帮助你理解:
import threading
import time
import logging
logging.basicConfig(
format='%(threadName)s:%(message)s',
level=logging.DEBUG,
)
NUM_OF_THREADS = 10
TIMEOUT = 5
def sleeping_thread(delay, cond):
logging.debug("Hi, I'm going to delay by %d sec." % delay)
time.sleep(delay)
logging.debug("I was sleeping for %d sec." % delay)
cond.acquire()
logging.debug("Calling notify().")
cond.notify()
cond.release()
def create_sleeping_thread(delay, cond):
return threading.Thread(target=sleeping_thread,
args=(delay, cond))
if __name__ == '__main__':
cond = threading.Condition(threading.Lock())
cond.acquire()
working_counter = NUM_OF_THREADS
for i in xrange(NUM_OF_THREADS):
t = create_sleeping_thread(i, cond)
t.start()
start_time = time.time()
while working_counter > 0 and (time.time() - start_time < TIMEOUT):
cond.wait()
working_counter -= 1
logging.debug('%d workers still working', working_counter)
cond.release()
logging.debug('Finish waiting for threads (%d workers still working)',
working_counter)
更多信息可以查看comp.programming.threads FAQ。