代码之家  ›  专栏  ›  技术社区  ›  R.Orteza

如何运行一个对象的多个实例,每个对象内有两个线程?

  •  0
  • R.Orteza  · 技术社区  · 1 年前

    我试图将两个线程函数封装在一个对象中,并运行该对象的几个实例。到目前为止,我只能在将线程拉到类之外的情况下运行对象。

    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()
    

    有没有一种方法可以将线程封装在类中,而不是将它们拉出来运行对象?

    3 回复  |  直到 1 年前
        1
  •  1
  •   Barmar    1 年前

    在类中定义一个方法,该方法运行两个函数,每个函数都在自己的线程中。然后从主线程调用该方法。

    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()
    
        2
  •  0
  •   R.Orteza    1 年前

    我想明白了。以下是在类中封装线程的方法:

    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()
    
        3
  •  0
  •   Mark Tolonen    1 年前

    为了完全封装, __init__ 可以创建并启动每个线程和 join 方法可以阻止它们。使用 __enter__ __exit__ 类实例可以与一起使用 with 以在对象超出范围时自动停止线程:

    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)
    

    输出

    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