2009-12-26 106 views
1

我正在编写类似于生产者 - 消费者问题的程序。这是我的主代码:终止前清理缓冲区

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; 
} 
} 

管道是ArrayBlockingQueue的包装并充当缓冲区。输出是一个将缓冲区中的元素输出的类。

我想确保PipeProcessor干净地终止,即当它被发信号关闭时,它会清除缓冲区。由于关闭钩子调用close()方法,所以我确定处理器关闭时缓冲区没有被填充, 这是正确的方法吗?谢谢。

回答

0

不确定为什么您在关闭时试图清理管道,为什么不丢弃它并让GC清理它?只要我能看到,你所需要的就是关闭和第一个循环。

+0

因为我想在关闭程序之前输出缓冲区中的所有剩余元素,而不是丢弃它们。 – 2009-12-26 10:10:05

1

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

的同时run()循环和它后面的行可以写成:

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

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

感谢您的提示:-) – 2009-12-26 10:51:15

0

如果要处理管道中的所有元素的过程中停止之前,我不认为我会实际上使用关闭钩子 - 我会在主代码中明确关闭管道,然后在让主线程完成之前等待它完成。我建议你将close()方法更改为阻塞,直到流水线结束,或者添加一个单独的方法(例如waitForPipelineToEmpty())。

通过这种方式,您可以使其更具可控性 - 特别是,这意味着您不会尝试处理事情,而系统的其他位正在清理自己的关机挂钩。

终止生产者/消费者队列的另一种方法是拥有一个标记值,意思是“立即停止”。然后,您只需将其馈入管道的末端(并避免添加更多“真实”值),并且您的处理器在看到该项目时就停下来。

+0

你是对的。但在我的情况下,我正在构建一个分析器,该分析器应该在分析程序终止时关闭。配置文件程序在管道上生成,而另一个线程PipedProcessor将使用该配置文件。 – 2009-12-26 10:29:12

1

我担心out.close()不一定会被调用。如果Pipe.get()像ArrayBlockingQueue.take()那样阻塞,并且它在检测到闭包时不返回标记值,那么在Pipe为空后在PipeProcessor上调用close()将不起作用,因为while(!close)条件不会再次评估。 (1)Pipe会始终关闭,(2)Pipe.get()检测到关闭,并且(3)它返回一些像Output一样可以处理的null的sentinel值。如果是这种情况,那么你的代码看起来不错。