Python threading.Thread、范围和垃圾收集

dat*_*olf 5 python multithreading garbage-collection destructor

假设我从 threading.Thread 派生:

from threading import Thread

class Worker(Thread):
    def start(self):
        self.running = True
        Thread.start(self)

    def terminate(self):
        self.running = False
        self.join()

    def run(self):
        import time
        while self.running:
            print "running"
            time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

任何具有启动线程的此类实例都必须主动终止其线程,然后才能进行垃圾回收(线程本身拥有引用)。所以这是一个问题,因为它完全违背了垃圾收集的目的。在这种情况下,有一些对象封装了一个线程,并且随着对象的最后一个实例超出范围,析构函数被调用以进行线程终止和清理。因此是一个析构函数

    def __del__(self):
        self.terminate()
Run Code Online (Sandbox Code Playgroud)

不会做的伎俩。

我认为很好地封装线程的唯一方法是使用低级thread内置模块和weakref弱引用。或者我可能遗漏了一些基本的东西。那么有没有比在weakref意大利面条式代码中纠缠不清更好的方法呢?

jwd*_*jwd 5

如何使用包装类(它具有-aThread而不是 is-a Thread)?

例如:

class WorkerWrapper:
    __init__(self):
        self.worker = Worker()
    __del__(self):
        self.worker.terminate()
Run Code Online (Sandbox Code Playgroud)

然后在客户端代码中使用这些包装类,而不是直接使用线程。

或者我想念一些东西(:

  • 虽然我没有听从你的建议,但它让我走上了正轨:工作人员现在以下列方式实例化一个线程:`self.worker_thread = Thread(target = WorkerClass.worker_function, args = (weakref(self),) )` 这允许 WorkerClass 实例超出范围并收集垃圾,这允许通过在析构函数中设置标志和 join() 来优雅地停止线程。 (2认同)