0cd*_*0cd 8 python multithreading
我有一个python程序产生了许多线程.这些线程持续2秒到30秒之间的任何时间.在主线程中,我想跟踪每个线程何时完成并打印消息.如果我只是顺序.join()所有线程和第一个线程持续30秒而其他线程更快完成,我将无法更快地打印消息 - 所有消息将在30秒后打印.
基本上我想阻塞,直到任何线程完成.一旦线程完成,就打印一条关于它的消息,如果任何其他线程仍处于活动状态,则返回阻塞状态.如果所有线程都已完成,则退出程序.
我能想到的一种方法是将队列传递给所有线程并阻塞queue.get().每当从队列接收到消息时,打印它,使用threading.active_count()检查是否有其他线程处于活动状态,如果是,则返回到queue.get()上的阻塞.这可以工作,但是这里所有线程都需要遵循在终止之前向队列发送消息的规则.
我想知道这是否是实现这种行为的传统方式还是有其他/更好的方法?
这是@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"
Run Code Online (Sandbox Code Playgroud)
为什么不让线程本身打印完成消息,或者在完成时调用其他完成回调?
您可以join
从主程序中仅使用这些线程,因此您将看到一堆完成消息,并且当它们全部完成时,您的程序将根据需要终止。
这是一个快速简单的演示:
#!/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!
Run Code Online (Sandbox Code Playgroud)