Mad*_*ist 4 python multithreading python-3.x
根据许多来源,包括这个问题,将可运行作为target参数传递__init__(带或不带argsand kwargs)比扩展类更可取Thread。
如果我创建一个可运行的对象,如何在self不扩展Thread类的情况下传递它正在运行的线程?例如,以下内容可以正常工作:
class MyTask(Thread):
def run(self):
print(self.name)
MyTask().start()
Run Code Online (Sandbox Code Playgroud)
但是,我看不到让这个版本工作的好方法:
def my_task(t):
print(t.name)
Thread(target=my_task, args=(), kwargs={}).start()
Run Code Online (Sandbox Code Playgroud)
这个问题是Python - How can I Implement a 'stoppable' thread? 的后续问题 ,我回答了,但可能不完整。
更新
我想到了一个技巧来使用以下方法来做到这一点current_thread():
def my_task():
print(current_thread().name)
Thread(target=my_task).start()
Run Code Online (Sandbox Code Playgroud)
问题:调用函数来获取理想情况下应该传入的参数。
更新#2
我发现了一个更黑客的解决方案,它看起来current_thread更具吸引力:
class ThreadWithSelf(Thread):
def __init__(self, **kwargs):
args = kwargs.get('args', ())
args = (self,) + tuple(args)
kwargs[args] = args
super().__init__(**kwargs)
ThreadWithSelf(target=my_task).start()
Run Code Online (Sandbox Code Playgroud)
除了极其丑陋之外(例如,通过强制用户仅使用关键字,即使这是文档中推荐的方式),这完全违背了不扩展Thread.
更新#3
另一个荒谬(且不安全)的解决方案:通过传入可变对象args并随后更新它:
def my_task(t):
print(t[0].name)
container = []
t = Thread(target=my_task, args=(container,))
container[0] = t
t.start()
Run Code Online (Sandbox Code Playgroud)
为了避免同步问题,您可以将其提高一个档次并实现另一层荒谬:
def my_task(t, i):
print(t[i].name)
container = []
container[0] = Thread(target=my_task, args=(container, 0))
container[1] = Thread(target=my_task, args=(container, 1))
for t in container:
t.start()
Run Code Online (Sandbox Code Playgroud)
我仍在寻找合法的答案。
看来您的目标是从任务本身内部访问当前正在执行任务的线程。您无法将线程作为参数添加到threading.Thread构造函数,因为它尚未构造。我认为有两个真正的选择。
如果您的任务运行多次,可能在许多不同的线程上运行,我认为最好的选择是threading.current_thread()从任务内部使用。这使您可以直接访问线程对象,用它您可以做任何您想做的事情。这似乎正是该函数设计的用例类型。
另一方面,如果您的目标是实现具有某些特殊特征的线程,那么自然的选择是子类化threading.Thread,实现您希望的任何扩展行为。
另外,正如您在评论中指出的,insinstance(current_thread(), ThreadSubclass)will return True,这意味着您可以使用这两个选项,并确保您的任务将能够访问您在子类中实现的任何额外行为。
| 归档时间: |
|
| 查看次数: |
3064 次 |
| 最近记录: |