【问题标题】:Is there a way to call a method of a class object thread and have it run in that specific thread?有没有办法调用类对象线程的方法并让它在该特定线程中运行?
【发布时间】:2020-10-13 17:55:26
【问题描述】:

上下文:

我有一个线程类,在一个 for 循环中被调用了 10 次。

对于类的每个对象,我为用户传递一个username,这取决于它在for循环中的位置,例如user0, user1, user2等。

我在类中创建了一个名为new_message() 的方法,它只是打印另一条消息。

在该类的def run() 方法中,我将username 作为键和new_message() 函数作为值添加到字典中

我的问题:

我尝试为其中一个用户调用 new_message() 函数,希望该函数可以在为该特定用户创建的线程中运行,但我认为它在主线程中运行,导致我的下一行代码等待。

所以我的问题是:

有没有办法调用类对象线程的方法并让它在该特定线程中运行?


请注意,这是我遇到的一个更大问题的代表,但我制作了一个模仿我的代码的最小复制示例。

代码:

import time

import threading

dict = {

}

class go(threading.Thread):
    def __init__(self, username):
        threading.Thread.__init__(self)
        self.username = username

    def run(self):
        dict[self.username] = self.new_message
        for count in range(10):
            print('Hello: '+self.username+'\n')
            time.sleep(10)

    def new_message(self):
        for count in range(10):
            print('How are you: '+self.username)
            time.sleep(2)


for count in range(10):
    username = ('user' + str(count))
    go(username).start()


what_user = input('What user')
dict[what_user]()

Print('This line shouldn't be waiting to print')

【问题讨论】:

    标签: python multithreading dictionary oop python-multithreading


    【解决方案1】:

    有没有办法调用类对象线程的方法并让它在该特定线程中运行?

    不,这是不可能的。您已经 start()ed 线程,这使它运行它的 run() 方法。您不能调用这样的方法在该特定线程中运行它——它只会在您观察到的调用它的线程上运行(它在您的主线程中运行)。

    您需要其他线程(我们称它们为工作线程)与外部提交的任务合作才能实现这一点。例如,您可以让工作线程在完成初始工作后监听工作队列,以获取任务(即函数)并运行它们。

    这是您代码的快速实现:

    import time
    
    import threading
    from queue import Queue
    
    dict = {}
    
    
    class Go(threading.Thread):
        def __init__(self, username, work_queue):
            threading.Thread.__init__(self)
            self.username = username
            self.work_queue = work_queue
    
        def run(self):
            self.initialize()
            while True:
                task = self.work_queue.get()
                task()
                self.work_queue.task_done()
    
        def initialize(self):
            dict[self.username] = {"func": self.new_message, "queue": self.work_queue}
            for _ in range(10):
                print("Hello: " + self.username + "\n")
                time.sleep(10)
    
        def new_message(self):
            for _ in range(10):
                print("How are you: " + self.username)
                time.sleep(2)
    
    
    for count in range(10):
        username = "user" + str(count)
        Go(username, Queue()).start()
    
    
    what_user = input("What user")
    selection = dict[what_user]
    queue, method = selection["queue"], selection["func"]
    queue.put(method)
    
    print("This line shouldn't be waiting to print")
    

    您会发现"This line shouldn't be waiting to print" 现在确实不会等待。主线程将其作为任务放入所选工作线程的队列中。工作人员在完成其self.initialize() 调用后将其接起。

    【讨论】:

    • 这非常有效,当self.initialize 还没有完成运行时,我只是很困惑while 循环是如何运行的
    • 它之前没有运行 -- 它在 self.initialize 之后运行。与此同时,另一个“任务”只是在队列中等待。使用self.initialize() 完成后,目标线程会拾取它。如果你想让它停止它正在做的事情,你需要添加一些条件逻辑来打破最初的 while 循环。
    • 我很困惑,我知道self.initialize首先运行,但是while循环,我不明白它是如何执行甚至被调用的,特别是因为self.initialize需要一段时间才能运行完成
    • self.initialize 在工作线程(不是主线程)中运行 100 秒。在此期间的某个时间,您选择用户;此时主线程将任务放入目标队列。工作线程在 100 秒后查看队列并看到一个任务在那里等待它。它拾取并运行它(即运行new_message 函数)。
    • 我明白了,所以def new_message(self) 也没有办法直接跑掉
    猜你喜欢
    • 1970-01-01
    • 2017-08-22
    • 2020-03-10
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 2018-08-27
    • 1970-01-01
    相关资源
    最近更新 更多