2012-05-03 97 views
7

我有一个python程序,产生了一些线程。这些线程持续2秒到30秒。在每个线程完成并打印消息时,我都希望跟踪主线程。如果我只是依次.join()所有线程,并且第一个线程持续30秒,其他线程完成得更快,我将无法更快地打印消息 - 所有消息都将在30秒后打印。在Python线程中,我如何跟踪线程的完成?

基本上我想阻止,直到任何线程完成。一旦一个线程完成,打印一条关于它的消息并返回到阻塞,如果任何其他线程仍然存在。如果所有线程都完成,则退出程序。

我可以想到的一种方法是将一个队列传递给所有线程并阻塞queue.get()。每当收到来自队列的消息时,打印它,使用threading.active_count()检查是否有其他线程处于活动状态,如果是,则返回到queue.get()上的阻塞。这将工作,但在这里所有的线程都需要遵循在终止之前将消息发送到队列的规则。

我在想,这是实现这种行为的传统方式还是有其他更好的方法?

回答

3

这里是一个可以让你从你的主线程中指定,而不是从你的目标函数打印其中的消息,上@ detly的答案的变化。这将创建一个包装函数,它调用您的目标,然后在终止之前打印消息。您可以修改此选项以在每个线程完成后执行任何标准清理。

#!/usr/bin/python 

import threading 
import time 

def target1(): 
    time.sleep(0.1) 
    print "target1 running" 
    time.sleep(4) 

def target2(): 
    time.sleep(0.1) 
    print "target2 running" 
    time.sleep(2) 

def launch_thread_with_message(target, message, args=[], kwargs={}): 
    def target_with_msg(*args, **kwargs): 
     target(*args, **kwargs) 
     print message 
    thread = threading.Thread(target=target_with_msg, args=args, kwargs=kwargs) 
    thread.start() 
    return thread 

if __name__ == '__main__': 
    thread1 = launch_thread_with_message(target1, "finished target1") 
    thread2 = launch_thread_with_message(target2, "finished target2") 

    print "main: launched all threads" 

    thread1.join() 
    thread2.join() 

    print "main: finished all threads" 
0

我不知道我看到使用的问题: threading.activeCount()

跟踪仍处于活动状态的线程数?

即使您不知道在启动之前要启动多少个线程,它似乎很容易跟踪。我通常通过列表理解生成线程集合,然后使用activeCount到列表大小的简单比较可以告诉您有多少完成。

在这里看到:http://docs.python.org/library/threading.html

或者,一旦你有你的线程对象,你可以使用线程对象中的.isAlive方法检查。

我只是扔到一个多线程程序我有这样的检查,它看起来罚款:

for thread in threadlist: 
     print(thread.isAlive()) 

给我的真列表/ false作为线程打开和关闭。所以你应该可以做到这一点,并检查任何错误,以查看是否有任何线程完成。

1

您可以让线程将其结果推送到threading.Queue。让另一个线程在该队列中等待并在出现新项目时立即打印该消息。

4

该线程需要使用Thread.is_alive()调用进行检查。

2

我的建议是循环这样

while len(threadSet) > 0: 
    time.sleep(1) 
    for thread in theadSet: 
     if not thread.isAlive() 
      print "Thread "+thread.getName()+" terminated" 
      threadSet.remove(thread) 

有1秒的睡眠,所以会有线程终止和消息之间有轻微的延迟打印出来。如果你能忍受这种延迟,那么我认为这是比你在问题中提出的解决方案更简单的解决方案。

3

为什么不只是让线程本身打印完成消息,或者在完成时调用其他完成回调?

你可以从你的主程序中看到这些线程,所以你会看到一堆完成消息,当你完成所有的事情时你的程序将会终止。

这里有一个快速和简单的例子:

#!/usr/bin/python 

import threading 
import time 

def really_simple_callback(message): 
    """ 
    This is a really simple callback. `sys.stdout` already has a lock built-in, 
    so this is fine to do. 
    """  
    print message 

def threaded_target(sleeptime, callback): 
    """ 
    Target for the threads: sleep and call back with completion message. 
    """ 
    time.sleep(sleeptime) 
    callback("%s completed!" % threading.current_thread()) 

if __name__ == '__main__': 
    # Keep track of the threads we create 
    threads = [] 

    # callback_when_done is effectively a function 
    callback_when_done = really_simple_callback 

    for idx in xrange(0, 10): 
     threads.append(
      threading.Thread(
       target=threaded_target, 
       name="Thread #%d" % idx, 
       args=(10 - idx, callback_when_done) 
      ) 
     ) 

    [t.start() for t in threads] 
    [t.join() for t in threads] 

    # Note that thread #0 runs for the longest, but we'll see its message first! 
0

由于我在应用程序中使用的线程的性质,我使用稍微不同的技术。为了说明这一点,这是一个测试程序带我写了脚手架的屏障类为我的线程类的一个片段:

while threads: 
     finished = set(threads) - set(threading.enumerate()) 
     while finished: 
      ttt = finished.pop() 
      threads.remove(ttt) 
     time.sleep(0.5) 

我为什么这样做呢?在我的生产代码中,我有时间限制,所以第一行实际上是“while threads and time.time()< cutoff_time”。如果我达到截止时间,然后有代码告诉线程关闭。