New*_*Guy 6 python multithreading restart python-multithreading
我有一个应用程序启动一系列线程.有时,其中一个线程死亡(通常是由于网络问题).如何正确检测线程崩溃并重新启动该线程?这是示例代码:
import random
import threading
import time
class MyThread(threading.Thread):
def __init__(self, pass_value):
super(MyThread, self).__init__()
self.running = False
self.value = pass_value
def run(self):
self.running = True
while self.running:
time.sleep(0.25)
rand = random.randint(0,10)
print threading.current_thread().name, rand, self.value
if rand == 4:
raise ValueError('Returned 4!')
if __name__ == '__main__':
group1 = []
group2 = []
for g in range(4):
group1.append(MyThread(g))
group2.append(MyThread(g+20))
for m in group1:
m.start()
print "Now start second wave..."
for p in group2:
p.start()
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我启动4个线程然后我开始4个线程.每个线程随机生成int介于0和10之间.如果int是4,则会引发异常.请注意,我没有join线程.我想要两个group1和group2线程列表都在运行.我发现如果我加入了线程,它会等到线程终止.我的线程应该是一个守护进程,因此应该很少(如果曾经)点击ValueErrorException这个示例代码显示并应该不断运行.通过加入它,下一组线程不会开始.
如何检测特定线程是否已死亡并重新启动该线程?
我在循环后尝试了以下for p in group2循环.
while True:
# Create a copy of our groups to iterate over,
# so that we can delete dead threads if needed
for m in group1[:]:
if not m.isAlive():
group1.remove(m)
group1.append(MyThread(1))
for m in group2[:]:
if not m.isAlive():
group2.remove(m)
group2.append(MyThread(500))
time.sleep(5.0)
Run Code Online (Sandbox Code Playgroud)
我从这个问题中采用了这种方法.
这个问题,isAlive()似乎总是返回True,因为线程永远不会重启.
编辑
在这种情况下使用多处理更合适吗?我找到了这个教程.如果我需要重新启动进程,是否更适合使用单独的进程?似乎重启线程很困难.
在评论中提到我应该检查is_active()线程.我没有在文档中看到这一点,但我确实看到了isAlive我目前正在使用的内容.正如我上面提到的,这会返回True,因此我永远无法看到线程已经死亡.
小智 7
我有类似的问题并偶然发现了这个问题。我发现 join 需要一个超时参数,一旦线程加入, is_alive 将返回 False 。所以我对每个线程的审核是:
def check_thread_alive(thr):
thr.join(timeout=0.0)
return thr.is_alive()
Run Code Online (Sandbox Code Playgroud)
这为我检测到线程死亡。
您可能会在除了您期望崩溃的地方之外进行尝试(如果它可以在您可以在整个运行函数周围执行的任何地方),并有一个具有其状态的指示符变量。
所以像下面这样:
class MyThread(threading.Thread):
def __init__(self, pass_value):
super(MyThread, self).__init__()
self.running = False
self.value = pass_value
self.RUNNING = 0
self.FINISHED_OK = 1
self.STOPPED = 2
self.CRASHED = 3
self.status = self.STOPPED
def run(self):
self.running = True
self.status = self.RUNNING
while self.running:
time.sleep(0.25)
rand = random.randint(0,10)
print threading.current_thread().name, rand, self.value
try:
if rand == 4:
raise ValueError('Returned 4!')
except:
self.status = self.CRASHED
Run Code Online (Sandbox Code Playgroud)
然后你可以使用你的循环:
while True:
# Create a copy of our groups to iterate over,
# so that we can delete dead threads if needed
for m in group1[:]:
if m.status == m.CRASHED:
value = m.value
group1.remove(m)
group1.append(MyThread(value))
for m in group2[:]:
if m.status == m.CRASHED:
value = m.value
group2.remove(m)
group2.append(MyThread(value))
time.sleep(5.0)
Run Code Online (Sandbox Code Playgroud)