如何进行线程化.Thread的start()调用run()以外的方法

时间:2016-11-01 16:09:37

标签: python multithreading

我有一个类有两个方法run()run_forever(),后者重复调用前者。我想在不同的线程上为类的不同实例运行run_forever(),但到目前为止,我还没有能够偏离threading.Thread调用run()的默认行为1}}。

以下是我尝试实现的简化版本:

import time
import threading

class Controller(object):
    def run(self):
        print("Running once...")

    def run_forever(self):
        while True:
            self.run()
            time.sleep(1)

class ThreadController(Controller, threading.Thread):
    def __init__(self, *args, **kwargs):
        Controller.__init__(self, *args, **kwargs)
        threading.Thread.__init__(self, target=self.run_forever)

if __name__ == "__main__":
    thread_controller = ThreadController()
    thread_controller.start()
    thread_controller.join()

如果我运行此脚本,它会打印Running once...一次,并且在target=self.run_forever的初始化中设置threading.Thread时,不会像我预期的那样每秒继续打印它。我如何修改此代码以实现所需的行为?

4 个答案:

答案 0 :(得分:2)

停止继承Controller

controller = Controller()
thread = threading.Thread(target=controller.run_forever)

答案 1 :(得分:2)

您实际上是在覆盖线程的run方法:您的ThreadController继承自ControllerThreadController类实现它自己的run

来自docs

  

标准run()方法调用传递给对象构造函数的可调用对象作为目标参数

但是您的run没有调用任何内容(不对目标做任何事情)。它只打印运行一次... 您看到的print单个Thread试图执行其run()方法。嗯...... 试图并且实际上取得了成功。的; - )

想到解决此问题的一些事情(虽然我个人可能会更改代码并尝试避免双重继承)会将Controller.run的名称更改为像.do

这样的东西
class Controller(object):
    def do(self):
        print("Running once...")

    def run_forever(self):
        while True:
            self.do()
            time.sleep(1)

答案 2 :(得分:1)

正如前面提到的,我也不喜欢多重继承,但是使用run方法将类作为线程本身。这使得ThreadController实际上就是它的名字所暗示的。我可以建议以下重新破解的代码:

class MyThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self, target=self.run_forever)

    def do(self):
        print("Running once...")

    def run_forever(self):
        while True:
            self.do()
            time.sleep(1)

class ThreadController(object):
    def __init__(self, *args, **kwargs):
        c = MyThread()
        c.start()
        c.join()

if __name__ == "__main__":
    thread_controller = ThreadController()

当然,除了可以将run_forever重命名为run并省略构造函数的target参数这一事实之外,我尊重这篇文章的标题:-)。

答案 3 :(得分:0)

我认为您希望Controller从Thread继承,然后不要覆盖run;

from threading import Thread

class Controller(Thread):

    def __init__(self, *args, **kwargs):
        super(Controller, self).__init__(*args, **kwargs)

    def run_once(*args, **kwargs):
        print("Running once...")

    def run_forever(*args, **kwargs):
        print("Running forever...")

运行一次;

Controller(target=Controller.run_once).start()

永远奔跑;

Controller(target=Controller.run_forever).start()