为什么在重新启动线程时需要重新创建实例?

时间:2013-01-12 12:35:56

标签: python multithreading

想象一下以下几个类:

Class Object(threading.Thread):
    # some initialisation blabla
    def run(self):
        while True:
            # do something
            sleep(1)

class Checker():
    def check_if_thread_is_alive(self):
        o = Object()
        o.start()

        while True:
            if not o.is_alive():
                o.start()

我想重新启动线程,以防它死了。这不起作用。因为线程只能启动一次。第一个问题。这是为什么?

据我所知,我必须重新创建Object的每个实例并调用start()再次启动该线程。在复杂Object s的情况下,这不是很实用。我将读取旧Object的当前值,创建一个新值并使用旧值在新对象中设置参数。第二个问题:这可以用更聪明,更简单的方式完成吗?

3 个答案:

答案 0 :(得分:15)

实现threading.Thread的原因是保持线程对象和操作系统的线程之间的对应关系。在主要操作系统中,线程无法重新启动,但您可以使用另一个线程ID 创建另一个线程。

如果娱乐是一个问题,则无需从threading.Thread继承您的类,只需将目标参数传递给Thread的构造函数,如下所示:

class MyObj(object):
    def __init__(self):
        self.thread = threading.Thread(target=self.run)
    def run(self):
        ...

然后,您可以访问线程成员来控制线程执行,并根据需要重新创建它。不需要MyObj娱乐。

答案 1 :(得分:1)

见这里: http://docs.python.org/2/library/threading.html#threading.Thread.start

  

每个线程对象最多只能调用一次。它安排了   object的run()方法在一个单独的控制线程中调用。

     

如果在on上多次调用此方法将引发RuntimeError   相同的线程对象。

线程不打算多次运行。您可能想要使用Thread Pool

答案 2 :(得分:0)

我相信,这与Thread类的实现方式有关。它包装了一个真正的OS线程,因此重新启动线程实际上会改变它的身份,这可能会令人困惑。

处理线程的更好方法实际上是通过目标函数/ callables:

class Worker(object):
    """ Implements the logic to be run in separate threads """
    def __call__(self):
        #  do useful stuff and change the state

class Supervisor():
    def run(self, worker):
        thr = None
        while True:
            if not thr or not thr.is_alive():
                thr = Thread(target=worker)
                thr.daemon = True
                thr.start()
            thr.join(1)  # give it some time