创建一个“单例” thread-如何在任一时间最多拥有 1 个线程实例

发布于 2025-01-06 04:45:10 字数 444 浏览 3 评论 0原文

我正在寻找一个从程序中的多个位置初始化并启动的类(从 threading.Thread 子类化)。我想避免的是,如果线程已经从其他地方运行,如果程序中的另一个地方尝试启动它,

t= somemodule.TheThread(some,args)
t.start()

程序可以继续运行(但只有当同一个线程尚未在此处或其他地方运行时,该线程才会启动)。

我可以想到一些不是很优雅的方法来通过设置标志来实现这一点,但必须有一个很好的方法来处理这个问题。我研究了带有装饰器或重写 new 的单例类型模式,但主要问题是,如果我保留相同的实例,则您不能(据我所知)多次调用 start,即使如果线程已完成。

我考虑过在另一个对象中创建线程对象,该对象可以检查当前线程是否仍在运行,但我无法弄清楚如何保持该线程的安全。

有人有什么想法吗?

I'm looking to have a class (subclassed from threading.Thread) that is initialised and started from multiple places in a program. What I want to avoid is if the thread is already running from somewhere else, if another place in the program trys to start it

t= somemodule.TheThread(some,args)
t.start()

the program can carry on (but the thread only starts if the same thread isn't already running here, or elsewhere).

I can think of a few not very elegant ways to achieve this with setting flags, but there must be a nice way of dealing with this. I looked at singleton type patterns with decorators or overriding new but the main problem is that if I keep the same instance is that you can't (that I'm aware) call start more than once, even if the thread has finished.

I thought about having the thread object created in anther object which can check to see if the current thread is still running, but I couldn't work out how to keep this thread safe.

Anyone got any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

攀登最高峰 2025-01-13 04:45:10

您应该使用一个函数来创建和启动线程,并且该函数可以使用自己的簿记来了解线程是否已经启动。不要忘记使簿记成为线程安全的!

试图让调用者相信他正在创建并启动一个线程,而实际上他可能没有,这是比其价值更多的麻烦。无论如何,将这种常见操作封装在函数中都是一个好主意,并且可以为您提供所需的控制。

You should use a function to create and start the thread, and that function can use its own bookkeeping to know whether the thread has been started already or not. Don't forget to make that bookkeeping thread-safe!

Trying to make the caller believe he is creating and starting a thread, when maybe he isn't, is more trouble than it is worth. Encapsulating this common operation in a function is a good idea in any case, and gives you the control you're seeking.

柒夜笙歌凉 2025-01-13 04:45:10

检查 somemodule.TheThread 线程是否处于活动状态的一种简单方法如下:

any(isinstance(thread, somemodule.TheThread)
    for thread in threading.enumerate())

One easy way to check if a somemodule.TheThread thread is alive is as follows:

any(isinstance(thread, somemodule.TheThread)
    for thread in threading.enumerate())
不及他 2025-01-13 04:45:10

在应用程序启动时启动线程并让它等待事件。如果事件被设置,线程将执行其工作,重置事件并再次等待它。一旦某个其他线程通过设置事件“启动”循环线程,任意数量的其他线程都可以调用“set”,直到循环线程完成其工作、清除事件并再次等待为止。

没有线程微管理,不可能有多个线程实例,没有线程不安全,没有标志,没有可疑的线程状态检查。

循环线程完成其工作和清除事件之间有一个小窗口,其中来自另一个线程的集合将被忽略。通过您选择的设计很难消除这种不确定性。您可以使用信号量而不是事件,并在顶部使用 acquire(false) 循环来检查信号量是否已发出信号,并确保其计数再次为零。如果信号量已发出信号,则线程可以再次运行其工作。如果信号量尚未发出信号,则可以等待它,直到发出信号为止。

Start the thread at app startup and have it wait on an event. If the event gets set, the thread does its work, resets the event and waits on it again. Once some other thread 'starts' the loop-thread by setting the event, any number of other threads can call 'set' to no effect until the loop-thread has done its work, cleared the event and is waiting again.

No thread micro-management, no possibility of there ever being more than one thread instance, no thread-unsafety, no flags, no dubious thread-state checking.

There is a small window between the loop-thread finishing its work and clearing the event where a set from another thread will be ignored. Such uncertainty is difficult to eliminate with the design you have chosen. You could use a semaphore instead of an event and use a acquire(false) loop at the top to both check if the semaphore has been signaled and also to ensure its count is zero again. If the semaphore has been signaled, the thread can run its work again. If the semaphore has not been signaled, it can be waited on until it is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文