3

我希望我的 while 循环最多为它在 for 循环中创建的所有线程阻塞 5 秒。但是,以下代码将被线程一一阻塞。我怎样才能接近我的目标?谢谢。

threads = []
while True:
    for 3:
        newThread = threading.Thread(..)
        threads.append(newThread)
        newThread.start()
        newThread.join(5)
4

3 回答 3

3

您需要使用条件变量(threading.Condition在 Python 中)。它允许等待谓词变为真。在您的情况下,谓词是all threads have finished work or time out exceeded. 这是创建十个线程并等待它们完成并有 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

于 2011-10-29T12:05:15.523 回答
2

要做的一件事是启动所有线程,然后遍历数组并加入。但我想,这仍然会等待总共 5*thread count 秒。或者,您可以创建一个额外的线程来无限期地等待您的线程。然后在你的主线程中,你可以等待额外的线程 5 秒。

于 2011-10-29T08:53:54.787 回答
0

您是否尝试每 5 秒生成一个线程,除非已经运行的线程之一结束,您希望更快地生成一个新线程?如果是这样,您可以使用 athreading.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
于 2011-10-29T09:01:41.240 回答