Home > Mobile >  How to design a python class with a thread member, that gets garbage collected
How to design a python class with a thread member, that gets garbage collected

Time:06-15

I have created a class A using the following pattern

class A:
    def __init__(self):
        self.worker = threading.Thread(target=self.workToDo)
        self.worker.setDaemon(daemonic=True)
        self.worker.start()
    
    def workToDo(self):
        while True:
             print("Work")

However, this design gets not garbage collected. I assume that this is due to a circular dependency between the running thread and its parent.

How can i design a class that starts a periodic thread that does some work, stops this thread on destruction and gets destructed as soon as all obvious references to the parent object get out of scope.

I tried to stop the thread in the ___del___ method, but this method is never called (i assume due to the circular dependency).

CodePudding user response:

There is no circular dependence, and the garbage collector is doing exactly what it is supposed to do. Look at the method workToDo:

def workToDo(self):
        while True:
             print("Work")

Once you start the thread, this method will run forever. It contains a variable named self: the instance of class A that originally launched the thread. As long as this method continues to run, there is an active reference to the instance of A and therefore it cannot be garbage collected.

This can easily be demonstrated with the following little program:

import threading
import time

def workToDo2():
    while True:
        print("Work2")
        time.sleep(0.5)

class A:
    def __init__(self):
        self.worker = threading.Thread(target=workToDo2, daemon=True)
        self.worker.start()
    
    def workToDo(self):
        while True:
             print("Work")
             time.sleep(0.5)
             
    def __del__(self):
        print("del")

A()
time.sleep(5.0)

If you change the function that starts the thread from self.workToDo to workToDo2, the __del__ method fires almost immediately. In that case the thread does not reference the object created by A(), so it can be safely garbage collected.

Your statement of the problem is based on a false assumption about how the garbage collector works. There is no such concept as "obvious reference" - there is either a reference or there isn't.

The threads continue to run whether the object that launched them is garbage collected or not. You really should design Python threads so there is a mechanism to exit from them cleanly, unless they are true daemons and can continue to run without harming anything.

I understand the urge to avoid trusting your users to call some sort of explicit close function. But the Python philosophy is "we're all adults here," so IMO this problem is not a good use of your time.

CodePudding user response:

Syntax of destructor declaration :

def del(self):

body of destructor

Note : A reference to objects is also deleted when the object goes out of reference or when the program ends. Example 1 : Here is the simple example of destructor. By using del keyword we deleted the all references of object ‘obj’, therefore destructor invoked automatically

Python program to illustrate destructor

class Employee:

# Initializing
def __init__(self):
    print('Employee created.')

# Deleting (Calling destructor)
def __del__(self):
    print('Destructor called, Employee deleted.')

obj = Employee() del obj

  • Related