终止前清理缓冲区

发布于 2024-08-15 19:45:48 字数 617 浏览 2 评论 0原文

我正在编写一个类似于生产者-消费者问题的程序。这是我的主要代码:

public class PipeProcessor {

private volatile boolean close = false;

Pipe pipe;
Output out;

public PipeProcessor(Pipe pipe)
{
    this.pipe = pipe;
}

public void run()
{
    while(!close)
    {
        out.output(pipe.get());
    }

    while(pipe.size() > 0)
        out.output(pipe.get());

    out.close();

}

public void close()
{
    close = true;
}
}

Pipe 是 ArrayBlockingQueue 的包装器并充当缓冲区。 Output 是一个类,它获取缓冲区中的元素并将其输出。

我想确保 PipeProcessor 干净地终止,即当它收到关闭信号时,它会清理缓冲区。由于 close() 方法是由关闭挂钩调用的,因此我确保在处理器关闭时缓冲区不会被填充, 这是正确的做法吗?谢谢。

I'm writing a program similar to the producer-consumer problem. Here's my main code:

public class PipeProcessor {

private volatile boolean close = false;

Pipe pipe;
Output out;

public PipeProcessor(Pipe pipe)
{
    this.pipe = pipe;
}

public void run()
{
    while(!close)
    {
        out.output(pipe.get());
    }

    while(pipe.size() > 0)
        out.output(pipe.get());

    out.close();

}

public void close()
{
    close = true;
}
}

Pipe is a wrapper for an ArrayBlockingQueue and acts as a buffer. Output is a class which takes an element in the buffer and outputs it.

I want to make sure that the PipeProcessor terminates cleanly, i.e. when it is signaled to close, it cleans the buffer. Since the close() method is called by a shutdown hook, I'm making sure that the buffer is not being filled while the processor is closing,
Is this the right way to do it? Thank you.

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

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

发布评论

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

评论(4

满栀 2024-08-22 19:45:48

看起来你的代码做了你想要它做的事情。如果你看一下你的命名,你可以让你的代码更容易理解,例如布尔值“close”可以被命名为“close”或“shuttingDown”,或者将其反转为“running”,这将导致代码更具可读性。

run() 中的 while 循环及其后面的行可以写为:

    while (running || pipe.size() > 0) {

        out.output(pipe.get());
    }

It looks like your code does what you want it to do. You could make your code easier to understand if you take a look at your naming, for instance the boolean "close" could be named "closing" or "shuttingDown" or inverse it to "running" which would result in more readable code imho.

The while loop in run() and the lines following it could be written as:

    while (running || pipe.size() > 0) {

        out.output(pipe.get());
    }
天冷不及心凉 2024-08-22 19:45:48

我担心 out.close() 不一定会被调用。如果 Pipe.get() 像 ArrayBlockingQueue.take() 并且它在检测到关闭时不会返回哨兵值,然后在 Pipe 为空后在 PipeProcessor 上调用 close() 将不会产生任何效果,因为 while(!close) 条件将不再评价。

但也许 (1) Pipe 总是首先关闭,(2) Pipe.get() 确实检测到关闭,(3) 它返回一些输出可以处理的哨兵值,如 null。如果是这种情况,那么您的代码看起来不错。

I'm concerned that out.close() won't necessarily get called. If Pipe.get() blocks like ArrayBlockingQueue.take() and it doesn't return a sentinel value when it detects closure, then calling close() on PipeProcessor after the Pipe is empty will have no effect because the while(!close) condition will not be evaluated again.

But maybe (1) the Pipe will always be closed first, (2) Pipe.get() does detect closure and (3) it returns some sentinel value like null which Output can handle. If this is the case, then your code looks good.

深海蓝天 2024-08-22 19:45:48

不知道为什么在关闭时要尝试清洁管道,为什么不丢弃它并让 GC 来清理它呢?据我所知,您所需要的只是关闭和第一个循环。

Not sure why you are trying to clean the pipe when you close, why don't you discard it and let the GC clean it up? All you need is the close and the first loop as far as I can see.

一口甜 2024-08-22 19:45:48

如果您想在进程停止之前处理管道中的所有元素,我认为我实际上不会使用关闭挂钩 - 我会在主代码中显式关闭管道,并等待它完成之前让主线程完成。我建议您更改 close() 方法以阻塞直到管道完成,或者添加一个单独的方法(例如 waitForPipelineToEmpty())。

通过这种方式,您可以使其更加可控 - 特别是,这意味着您不会在系统的其他部分在关闭挂钩中自行清理时尝试处理事物。

终止生产者/消费者队列的一种替代方法是使用一个哨兵值,这意味着“立即停止”。然后,您只需将其输入管道的末尾(并避免添加任何更多的“真实”值) - 当您的处理器看到该项目时,它就会停止。

If you want to process all the elements in the pipeline before the process stops, I don't think I'd actually use a shutdown hook - I'd shut the pipeline down explicitly in the main code, and wait for it to complete before letting the main thread finish. I suggest you either change the close() method to block until the pipeline has finished, or add a separate method (e.g. waitForPipelineToEmpty()).

In this way you can make it all more controllable - in particular, it means you won't be trying to process things while other bits of the system are cleaning themselves up in shutdown hooks.

One alternative way of terminating a producer/consumer queue is to have a sentinel value which means "stop now". Then you just feed that into the end of the pipeline (and avoid adding any more "real" values) - and your processor just stops when it sees that item.

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