Java 关闭时了解关闭请求标志

Java 关闭时了解关闭请求标志,java,multithreading,queue,Java,Multithreading,Queue,我正在阅读B.Goetz JCIP,在第7.2节中遇到了一些关于基于线程的服务的误解。代码如下: public class LogWriter{ private final BlockingQueue<String> queue; private final LoggerThread logger; public LogWriter(Writer writer){ this.queue = new LinkedBlockingQueue<String

我正在阅读B.Goetz JCIP,在第7.2节中遇到了一些关于基于线程的服务的误解。代码如下:

public class LogWriter{

    private final BlockingQueue<String> queue;
    private final LoggerThread logger;

public LogWriter(Writer writer){
    this.queue = new LinkedBlockingQueue<String>(CAPACITY);
    this.logger = new LoggerThread(writer);
}

public void start(){ logger.start(); }

public void log(String msg) throws InterruptedException {
    queue.put(msg);
} 

private class LoggerThread extends Thread {
    private final PrintWriter writer;
    public void run() {
        try{
            while(true)
               writer.println(queue.take());
        } catch(InterruptedException ignored){
        } finally {
            writer.close();
        }
     }
}
现在他说

log的实现比act sequnce更简单:生产者可以 请注意,服务尚未关闭,但仍在排队 关闭后的消息,再次,生产者有风险 可能在日志中被阻止,并且永远不会解锁

这个问题我不清楚

如果使用者将队列排到某个集合,则会使
log()
中被阻止的任何生产者解锁。即使某些生产者试图将日志消息放入队列,它也不会被阻止。我看到的唯一一件事是,由于队列已耗尽,因此不会记录此消息


问题:他为什么说制作人应该被封锁,永远不能解锁。我错过了什么?

如果您查看
阻塞队列
文档,您可以看到:

另外支持等待队列的操作的队列 若要在检索元素时变为非空,并等待空格变为空 存储元素时在队列中可用


也就是说,如果队列中没有更多空间,生产者可能会被阻止:如果服务已关闭,队列将不再耗尽。

由于代码不完整,很难说出作者的意图。记录器线程可能还会检查
shutdownRequested
以停止日志记录:

public void run() {
    try{
        while(shutdownRequested)
           writer.println(queue.take());
    } catch(InterruptedException ignored){
    } finally {
        writer.close();
    }
 }

如果你写这个,考虑一个场景,当队列满了,并且在“代码>队列中有线程被阻塞时,请停止。放进< /COD>”:日志线程停止调用<代码>队列。p>


即使情况并非如此,变量
shutdownRequested
也存在竞争条件。线程可能会在读取变量和消息在
log
方法中排队之间请求关闭,因此请求关闭后消息仍会排队。

您能发布完整的代码吗?
shutdownsrequested
是否仅在
log
方法中使用,或者也在记录器线程中使用?@Joni这是完整的。他没有提供更多详细信息。@Joni logger线程是一个内部类,但当请求关闭时,我们只需将标志设置为
true
,然后使用者清空队列。因此,所有在
log()
中哭泣的记录器都将解锁。唯一可能发生的情况是,大于队列容量的线程数会重现这种竞争条件……我同意,这应该只适用于多线程和samll容量的情况。但仍然有可能。
public void run() {
    try{
        while(shutdownRequested)
           writer.println(queue.take());
    } catch(InterruptedException ignored){
    } finally {
        writer.close();
    }
 }