2015-11-23 3 views
8

Hier ist der Code:Kann ich Collection.size() verwenden, um den Zähler in diesem Code zu ersetzen?

public class LogService { 
    private final BlockingQueue<String> queue; 
    private final LoggerThread loggerThread; 
    private final PrintWriter writer; 
    @GuardedBy("this") private boolean isShutdown; 
    @GuardedBy("this") private int reservations; // <-- counter 
    public void start() { loggerThread.start(); } 
    public void stop() { 
     synchronized (this) { isShutdown = true; } 
     loggerThread.interrupt(); 
    } 
    public void log(String msg) throws InterruptedException { 
     synchronized (this) { 
      if (isShutdown) 
       throw new IllegalStateException(...); 
      ++reservations; 
     } 
     queue.put(msg); 
    } 
    private class LoggerThread extends Thread { 
     public void run() { 
      try { 
       while (true) { 
        try { 
         synchronized (LogService.this) { 
          if (isShutdown && reservations == 0) 
           break; 
         } 
         String msg = queue.take(); 
         synchronized (LogService.this) { 
          --reservations; 
         } 
         writer.println(msg); 
        } catch (InterruptedException e) { /* retry */ } 
       } 
      } finally { 
       writer.close(); 
      } 
     } 
    } 
} 

Es ist ein Ausschnitt aus dem Buch Java Concurrency in Practice, und ich bin darüber nachgedacht vielleicht der Zähler reservations unnötig ist, da wir einfach queue.size() verwenden könnte die Zahl der bekommen Elemente in queue.

Bin ich richtig?

+1

Warteschlange 'put' und' get' ist nicht synchronisiert. 'Änderung der Reservierung 'ist. –

Antwort

5

Nein, das würde tatsächlich ein Deadlock erstellen.

Sie müssten put und take synchronisieren, wenn Sie parallel size verwenden möchten. Aber take blockiert und Sie würden jetzt einen blockierenden take Aufruf für das gleiche Objekt wie der put Aufruf synchronisiert haben. take kann nicht dauern, bis etwas put ist. put kann nicht gestellt werden, bis take das Schloss aufgibt. Das ist eine Sackgasse.

+0

Ich schaute durch den Quellcode von 'Put' und' Take' Methode, und es scheint, dass sie mit 'Lock' synchronisiert sind. – user2916610

+0

@ user2916610 die Frage wäre, wenn "Größe" auch synchronisiert wird. – djechlin

+0

'Größe' ist auch synchronisiert. – user2916610

0

Mit „Vorbehalten“ Variable ist ein gutes Domain-Design, weil es als Größe viel aussagekräftiger ist, können Sie verwenden, Domänenkonzept wie Gesamtzahl der Reservierung zur Verfügung etc

Auf der Leistungsseite

auszudrücken ArrayBlockingQueue - Calling-Size-Funktion wird in Langsamkeit resultieren, weil es Sperre erhält, um die Größe zu lesen, und das wird verlangsamen, nehmen Sie oder legen Sie auch Operation.

LinkedBlockingQueue - Calling-Größe ist atomare/volatile lesen und es hat Leistungskosten.

Verwandte Themen