跟踪不同线程上对象实例的状态?

发布于 2024-10-29 18:40:58 字数 529 浏览 0 评论 0原文

我正在空闲时间编写一个图像板刮刀,主要教我有关线程的知识。目前,我正在使用生产者/消费者类型模式来促进这项工作。但是,我遇到了问题。

现在,我有“队列处理器”,可以观察特定类型的线程安全队列并对其进行操作。这些队列处理器每 X 秒轮询一次目标队列,如果队列中有一个项目等待处理,则队列处理器会将该项目出队,启动一个包含该项目的新线程,然后启动该线程。在每个线程上,调用长时间运行的方法(例如连接到网站和下载文件)。通过这种方式,每个项目都有自己的线程来运行。

我很难弄清楚如何在每个线程上处理每个项目时报告其状态。

例如,假设我们有主线程 MT。 MT 生成子线程 T1、T2、T3、T4 和 T5。每个线程上都有一个对应的对象,O1...O5。这些对象在其线程上进行处理时可以处于三种不同的状态 - S1、S2、S3。

当对象O的状态发生变化时,如何向主线程MT报告每个对象O的状态S?

我尝试使用事件来报告状态,但我遇到了一些奇怪的结果。我用谷歌搜索了一些关于使用线程和事件的信息,但没有走得太远。

任何帮助将不胜感激。

谢谢。

I am writing an image board scraper in my free time to teach me mostly about threading. Currently I am using a producer/consumer type pattern to facilitate this effort. However, I am running into a problem.

Right now, I have "queue processors" that observe and act upon specific types of thread-safe queues. These queue processors poll the targeted queue every X seconds, and, if there is an item on the queue waiting to be processed, the queue processor de-queues that item, spins up a new thread with the item, and starts the thread. On each thread, long-running methods are called (like connecting to the website and downloading the file). In this manner, each item gets its own thread to run on.

I am having a difficult time figuring out how to report the status of each item while it is being processed on each thread.

For example, let's say we have main thread MT. MT spawns child threads T1, T2, T3, T4, and T5. On each thread is a corresponding object, O1...O5. These objects can be in, say, three different states- S1, S2, S3- while it is being processed on its thread.

How can I report the status, S of each object O to the main thread MT when the status of object O changes?

I tried using events to report the status, but I'm encountering some wonky results around that. I googled a bit about using threads and events, but didn't get very far.

Any help would be appreciated.

Thank you.

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

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

发布评论

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

评论(1

盛装女皇 2024-11-05 18:40:58

一种方法是创建另一个线程安全队列,用于报告状态更新。每次您的线程更改其状态时,它都会推送一个元组/对象,其中包含作业的唯一标识符、新状态、线程 ID 以及您认为必要的任何其他内容。

完成此操作后,您将遇到另一个问题:谁将轮询队列?您可以在检查作业队列之间使用主线程来完成此操作,但这可能很丑陋,并且可能不必要地减慢处理速度。您也可以生成另一个线程来执行此操作,但我猜您需要将状态报告给主线程,因此这没有帮助。

实际上有一种更好的方法来构建程序。您可以创建一个线程池并让作业线程自行进行轮询,而不是让主线程不断轮询作业队列并创建线程(这非常昂贵)。这将使主线程可以自由地轮询状态队列,等待它正在寻找的任何事件。

下面是一些伪代码来说明这个概念:

main_thread()
    ...
    thread_pool = create_pool(get_core_count());
    thread_pool.execute(worker_thread);

    while(true)
         status = status_queue.pop_blocking();
         if (check_status(status) == WE_BE_DONE) 
             break;

    thread_pool.interrupt();
    ...

worker_thread()
    while(true)
        job = job_queue.pop_blocking();
        process_job(job);
        status_queue.push({job.id, thread_id, WE_DONE});

本质上,它的作用是创建一个线程池,其中每个 CPU 核心包含一个工作线程(从默认值开始)。接下来,它在每个工作线程中执行函数worker_thread(该函数应该是不言自明的)。然后主线程不断检查状态队列中是否有某个未指定的事件。一旦发生这种情况,它就会杀死工作线程并恢复执行程序的其余部分。

示例中值得注意的三件事。首先,我建议在手动轮询实现上使用阻塞 pop 调用(示例中的 pop_blocking)。它使用起来更简单,而且效率可能更高。接下来,我使用 thread_pool.interrupt() 来终止作业线程,但这可能不是最明智的方法,具体取决于您使用的语言或库。如果您的语言支持此类内容,那么将 do_job(job) 调用包含在 try catch 语句中可能也是一个好主意。

请注意,由于您的问题很少涉及细节(所使用的语言),因此您肯定需要调整解决方案以适应您想要完成的任何任务。这仍然应该为您提供一个良好的起点。

One way to do it would be to create another thread-safe queue which would be used to report status updates. Every time your thread changes its status, it would push a tuple/object containing the unique identifier of the job, the new status, the thread id and whatever else you deem necessary.

Once you've done that, you'll hit another problem: who will poll the queue? You could do it with your main thread in between its checks to the job queue but that could be ugly and could unnecessarily slow down the processing. You could also spawn another thread for doing just this but I'm guessing you need the status to be reported to the main thread so this doesn't help.

There's actually a better way to structure the program. Instead of having the main thread continuously poll the job queue and create threads (which is pretty expensive), you could instead create a thread pool and let the job threads do the polling themselves. This will leave the main thread free to poll the status queue waiting for whatever event it's looking for.

Here's some pseudo code to illustrate the concept:

main_thread()
    ...
    thread_pool = create_pool(get_core_count());
    thread_pool.execute(worker_thread);

    while(true)
         status = status_queue.pop_blocking();
         if (check_status(status) == WE_BE_DONE) 
             break;

    thread_pool.interrupt();
    ...

worker_thread()
    while(true)
        job = job_queue.pop_blocking();
        process_job(job);
        status_queue.push({job.id, thread_id, WE_DONE});

Essentially, what this does is create a thread pool that contains one worker thread per CPU core you have (an ok default to start with). Next up, it executes the function worker_thread in each worker thread (the function should be self-explanatory). The main thread then continuously checks the status queue for a certain unspecified event. Once that's occurred, it kills off the worker threads and resume executing the rest of the program.

Three things worth noticing in the example. First off, I recommend using a blocking pop call (pop_blocking in the example) over a manual polling implementation. It's a lot simpler to use and probably far more efficient. Next, I used thread_pool.interrupt() to kill off the job threads but it might not be the smartest way to do it depending on the language or library you're using. It's probably also a good idea to surround the do_job(job) call in a try catch statement if your language supports that kind of things.

Note that since your question is pretty light on details (the language being used for one), you'll most definitely need to adapt the solution to whatever you're trying to accomplish. This should still give you a good starting point.

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