我想知道如何检查父线程是否仍然存活/卡住。基本上我有一个父线程向孩子发送命令。如果父线程死亡或遇到死锁情况,我不希望孩子继续生活。以下是我迄今为止实施的基本框架。
from Queue import Queue
from threading import Thread
class myClass:
def __init__(self):
self.currentCommand = Queue()
t = Thread(target=self._run)
t.start()
def close(self):
self._sendCommand("close")
def _run(self):
while True:
if self.currentCommand.empty():
pass
#do some task
else:
command = self.currentCommand.get()
if command == "close":
#clean up
self.currentCommand.task_done()
break
else:
#do command task
self.currentCommand.task_done()
def _sendCommand(self, command):
self.currentCommand.put(command)
self.currentCommand.join()
我的一个想法是定期向父母发送计算机时间给孩子。如果时间大于设定值,孩子就会死亡。是否有更简单或更有效的方法?同样在python文档中,线程类中有一个isAlive方法,但我不确定如何使用它。
答案 0 :(得分:1)
您可以将Event
对象传递给子线程,它可以检查父线是否表示退出。然后你只需用一个finally
包装父线程中的临界区,无论如何都会设置该位:
import time
from threading import Thread, Event
def child(quit):
for _ in xrange(10):
if quit.isSet():
print "Parent is dead. Leaving child."
return
print "Child alive"
time.sleep(.5)
def parent():
quitEvent = Event()
t = Thread(target=child, args=(quitEvent,))
t.start()
try:
time.sleep(2)
raise Exception("Parent thread raises exception")
finally:
quitEvent.set()
t.join()
if __name__ == "__main__":
t = Thread(target=parent, args=())
t.start()
t.join()
虽然父线程在其自己的工作中死锁的问题可能需要像你建议的“心跳”方法,它会周期性地指示它是活着的。您可以使用传递给子项的队列执行此操作,也可以继续使用Event对象。父母会定期设置事件,孩子会期望按一定的时间间隔设置事件,然后立即将其清除。
以下是使用Event
作为心跳的示例,如果父级可能已死锁且未签入:
def child(heartbeat):
for _ in xrange(10):
if not heartbeat.isSet():
print "Parent is dead. Leaving child."
return
heartbeat.clear()
print "Child alive"
time.sleep(1)
def parent():
heartbeat = Event()
heartbeat.set()
t = Thread(target=child, args=(heartbeat,))
t.start()
i = 0
while i < 20:
print "Parent alive"
i += 1
heartbeat.set()
time.sleep(.1)
print "Parent done looping...pretending to be deadlocked"
time.sleep(5)
t.join()
由于父母正在做自己的工作,它正在设置心跳位。孩子正在定期检查这个位。如果它发现未设置父级,则它假定它已死并退出。您需要建立适当的心跳间隔。父母需要比孩子检查更频繁地检查,或者孩子可能很快检查并认为父母已经离开。
答案 1 :(得分:1)
如果您以某种方式与子节点共享父线程对象,则可以使用isAlife
:
parent_thread = None
def child():
while True:
time.sleep(1)
if not parent_thread.isAlive():
break
print('child alife')
def parent():
t = threading.Thread(target=child)
t.start()
for i in range(10):
print('parent alife')
time.sleep(1)
parent_thread = threading.Thread(target=parent)
parent_thread.start()