Python:在 while 循环中使用 join() 的线程

发布于 2024-12-12 17:46:32 字数 265 浏览 0 评论 0原文

我希望 while 循环在 for 循环中创建的所有线程最多阻塞 5 秒。然而,下面的代码会被线程一一阻塞。我怎样才能实现我的目标?谢谢。

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

I would like my while loop to block at most 5 seconds for all threads it creates in the for loop. However, the following code will block by the threads one by one. How can I approach my goal? Thanks.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

卸妝后依然美 2024-12-19 17:46:32

您需要使用条件变量(Python 中的threading.Condition)。它允许等待谓词变为真。在您的情况下,谓词是所有线程都已完成工作或超时。下面的代码创建了 10 个线程,并等待它们以 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 常见问题解答

You need to use condition variable (threading.Condition in Python). It allows to wait for a predicate to become true. In your case the predicate is all threads have finished work or time out exceeded. Here is code which creates ten threads and waits until they are finished with 5sec time out. Verbose logs will help you:

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)

Further information at comp.programming.threads FAQ.

小…楫夜泊 2024-12-19 17:46:32

要做的一件事是启动所有线程,然后迭代数组并连接。但我想,这仍然会等待总共 5*线程计数秒。或者,您可以创建一个额外的线程,它只是无限期地等待您的线程。然后在你的主线程中你可以等待额外的线程 5 秒钟。

One thing to do is start all the threads, and then iterate over the array and join. But I suppose, this would still wait up to a total of 5*thread count seconds. Alternatively, you could create one additional thread that simply waits for your threads indefinitely. Then in your main thread you can just wait for the extra thread for 5 seconds.

握住我的手 2024-12-19 17:46:32

您是否尝试每 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

Are you trying to spawn a thread every 5 seconds, except if one of the already-running threads ends, you wish to spawn a new thread sooner? If so, you could use a threading.Event to signal when a worker thread ends, and use event.wait(timeout) to block at most 5 seconds for the event:

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()

yields

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文