2016-04-10 5 views
1

Ich lese B. Goetz JCIP und stoßen auf einige Missverständnisse im Abschnitt 7.2 über cancellin Thread-basierte Dienste. Hier ist der Code:Verständnis Shutdown angefordert Flag beim Herunterfahren

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

Er sagte, dass solche Service bietet keine Möglichkeit, es zu beenden. Er gibt eine andere Alternative dazu:

public void log(String msg) throws InterruptedException { 
    if(!shutdownRequested) 
      queue.put(msg); 
    else 
      throw new IllegalArgumentException("logger is shut down"); 
} 

Jetzt sagt er, dass

Die Implementierung von Protokoll ist Chek-als-act sequnce: Hersteller können beobachten, dass der Dienst noch nicht geschlossen worden, nach unten, aber immer noch Warteschlange Nachrichten nach dem Herunterfahren, wieder mit dem Risiko, dass der Hersteller möglicherweise im Protokoll blockiert werden und niemals entsperrt werden.

Das betonte ist mir nicht klar.

Wenn der Verbraucher die Warteschlange zu einer Sammlung entleerte, werden alle Hersteller gesperrt in log() entsperrt. Selbst wenn einige Produzenten versuchen, eine Protokollnachricht in die Warteschlange zu stellen, wird sie nicht blockiert. Das einzige, was ich sehe, ist, dass diese Nachricht nicht protokolliert wird, da die Warteschlange leer ist.

FRAGE: Warum tut er sagt, dass die Hersteller blockiert werden mught und nie freigeschaltet. Was habe ich verpasst?

+0

Können Sie den vollständigen Code veröffentlichen? Wird 'shutdownRequested' nur in' log' Methode oder auch im Logger Thread verwendet? – Joni

+1

@Joni Das ist der volle. Er hat nicht mehr Details angegeben. –

+0

@Joni Logger-Thread ist eine innere Klasse –

Antwort

1

Wenn Sie BlockingQueue doc können Sie sehen:

Eine Queue, die zusätzlich Operationen unterstützt, die für die Warteschlange warten nicht leer zu werden, wenn ein Element abrufen, und warten Raum werden verfügbar in der Warteschlange beim Speichern eines Elements.

I.e. Der Producer kann blockiert werden, wenn in der Warteschlange kein Platz mehr ist: Wenn der Service heruntergefahren wurde, wird die Warteschlange nicht mehr gelöscht.

+0

Aber wenn Shutdown angefordert wird, setzen wir nur die Flagge auf "wahr" und dann den Verbraucher die Warteschlange entleeren. Also, alle Logger, die in 'log()' verschwinden, werden entsperrt. Das einzige, was passieren kann, ist, dass die Anzahl der Threads größer als die Kapazität der Warteschlange solche Race-Bedingungen reproduzieren. –

+0

Ich stimme zu, dies sollte nur für den Fall von vielen Threads und samll Kapazität möglich sein. Aber immer noch möglich. –

1

Da der Code unvollständig ist, ist es schwer zu sagen, was der Autor beabsichtigt hat. Vermutlich der Logger Thread prüft auch shutdownRequested Protokollierung zu stoppen:

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

Wenn Sie diese Zeilen schreiben, ein Szenario, in dem die Abschaltung angefordert, wenn die Warteschlange voll ist und es blockieren Threads auf queue.put: der Logger-Thread beendet queue.take Aufruf und diese Threads bleiben für immer blockiert.

Auch wenn das nicht der Fall war, gibt es eine Racebedingung mit der Variablen shutdownRequested. Ein Thread kann das Herunterfahren anfordern, da die Variable gelesen wird und die Nachricht in der log-Methode in die Warteschlange gestellt wird, sodass Nachrichten nach dem Herunterfahren weiterhin in die Warteschlange gestellt werden.