0

I'm trying to wrap two threaded functions inside an object and run a couple of instances of the object. So far I could only run the objects if I pull the threading outside the class.

import threading

class MyObject:
    
    def __init__(self, item_id):
        self.item_id = item_id

    def func_one(self):
        # do stuff

    def func_two(self):
        # do another thing

# initialize objects
obj1 = MyObject("item-01")
obj2 = MyObject("item-02")

# create threads for each object
thread1_obj1 = threading.Thread(target=obj1.func_one)
thread2_obj1 = threading.Thread(target=obj1.func_two)
thread1_obj2 = threading.Thread(target=obj2.func_one)
thread2_obj2 = threading.Thread(target=obj2.func_two)

# start and join threads
thread1_obj1.start()
thread2_obj1.start()
thread1_obj2.start()
thread2_obj2.start()

thread1_obj1.join()
thread2_obj1.join()
thread1_obj2.join()
thread2_obj2.join()

Is there a way to encapsulate the threads inside the class instead of pulling them out to run the the objects?

1
  • Style note: Your thread1_obj1 variable and your thread1_obj2 variables refer to different threads, but they both have "thread1" in their names. In an enterprise-grade software engineering project, a code reviewer probably would ask you to change their names. E.g.; thread1_obj1, thread2_obj2, thread3_obj1, and thread4_obj2. Commented Feb 7, 2024 at 19:17

3 Answers 3

1

Define a method in the class that runs both functions, each in its own thread. Then call that method from the main thread.

import threading

class MyObject:
    
    def __init__(self, item_id):
        self.item_id = item_id

    def func_one(self):
        # do stuff

    def func_two(self):
        # do another thing

    def run_threads(self):
        self.thread1 = threading.Thread(target=self.func_one)
        self.thread2 = threading.Thread(target=self.func_two)
        self.thread1.start()
        self.thread2.start()

    def join_threads(self):
        self.thread1.join()
        self.thread2.join()

obj1 = MyObject("item-01")
obj2 = MyObject("item-02")

obj1.run_threads()
obj2.run_threads()

obj1.join_threads()
obj2.join_threads()
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! This does encapsulate the threads inside the object and can run multiple instances of the object!
0

I figured it out. Here's the way to encapsulate the threads inside the class:

import threading

class MyObject:
    
    def __init__(self, item_id):
        self.item_id = item_id
        self.t1 = threading.Thread(target=self.func_one)
        self.t2 = threading.Thread(target=self.func_two)
    
    def thread_start(self):
        self.t1.start()
        self.t2.start()
    
    def thread_join(self):
        self.t1.join()
        self.t2.join()

    def func_one(self):
        # do stuff

    def func_two(self):
        # do another thing

# initialize objects
obj1 = MyObject("item-01")
obj2 = MyObject("item-02")

# run and join objects' threads
obj1.thread_start()
obj2.thread_start()
obj1.thread_join()
obj2.thread_join()

Comments

0

To completely encapsulate, __init__ can create and start each thread and a join method can stop them. Using __enter__ and __exit__ the class instances can be used with with to automatically stop the threads when the objects go out-of-scope:

import threading
import time

class MyObject:

    def __init__(self, item_id):
        self.item_id = item_id
        self.thread1 = threading.Thread(target=self.func_one, daemon=True)
        self.thread2 = threading.Thread(target=self.func_two, daemon=True)
        self.running = True
        self.thread1.start()
        self.thread2.start()

    def func_one(self):
        while self.running:
            print(f'{self.item_id} func_one')
            time.sleep(1)

    def func_two(self):
        while self.running:
            print(f'{self.item_id} func_two')
            time.sleep(1)

    def join(self):
        self.running = False
        self.thread1.join()
        self.thread2.join()

    def __enter__(self):
        return self

    def __exit__(self, exec_type, exc_val, exc_tb):
        self.join()

with MyObject("item-01") as obj1, MyObject('item-02') as obj2:
    time.sleep(3)

Output:

item-01 func_one
item-01 func_two
item-02 func_one
item-02 func_two
item-01 func_one
item-02 func_two
item-02 func_one
item-01 func_two
item-01 func_one
item-01 func_two
item-02 func_two
item-02 func_one
item-01 func_one
item-01 func_two

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.