2015-04-12 16 views
0

我有關於Java 7 ConcurrentLinkedQueue的以下問題。讓我們假設我有下面的類:使用ConcurrentLinkedQueue序列化訪問Collection <T>

public class Blah { 
    private ConcurrentLinkedQueue<String> queue; 

    public Blah() { 
     queue = new ConcurrentLinkedQueue<String>(); 
    } 

    public void produce(String action, String task) throws InterruptedException { 
     synchronized(queue) { 
      while(queue.size() >= 8) 
       queue.wait(); 
      queue.add(action + "#" + task); 
      queue.notifyAll(); 
     } 
    } 

    public void consume() throws InterruptedException { 
     synchronized(queue) { 
      while(queue.size() <= 0) 
       queue.wait(); 
      String element = queue.poll(); 
      StringTokenizer strTok = new StringTokenizer(element, "#"); 
      String action = strTok.nextToken(); 
      String task = strTok.nextToken(); 
      /** 
      * Operate on request 
      */ 
      queue.notifyAll(); 
     } 
    } 
} 

的生產和消費的功能將併發線程,以便生成/從列表中刪除線程/調用。我實現了之前的函數consume()和produce(),以便序列化隊列中元素的添加/刪除。是上面的要求,還是ConcurrentLinkedQueue處理?我在問,因爲我不想降低我的代碼的性能。

謝謝 尼克

+0

爲什麼你在地球上同步? –

+0

@Boris因爲我希望自動執行關鍵部分內的所有操作。 –

+0

這是'ConcurrentLinkedQueue'。如果使用正確,它保證原子性和可見性。你正在將一個非阻塞的'Queue'強制轉換爲['BlockingQueue'](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html)。 **別**。 –

回答

1

TL; DR:您正在使用專門設計爲無阻塞的Queue作爲BlockingQueue

public class Blah { 
    private BlockingQueue<String> queue; 

    public Blah() { 
     queue = new LinkedBlockingQueue<>(8); 
    } 

    public void produce(String action, String task) throws InterruptedException { 
     while (true) { 
      queue.put(action + "#" + task); 
     } 
    } 

    public void consume() throws InterruptedException { 
     while (true) { 
      final String[] data = queue.take().split("#"); 
      final String action = data[0]; 
      final String task = data[1]; 
     } 
    } 
} 

BlockingQueue8元件限定:

您的代碼可以作爲被重寫。如果隊列已滿,put將會阻塞。如果隊列爲空,則take將會阻塞。

不需要同步。

另外,StringTokenizer已棄用。我建議你使用class這樣的東西:

public class Data { 
    private final String action; 
    private final String task; 

    public Data(final String action, final String task) { 
     this.action = action; 
     this.task = task; 
    } 

    public String getAction() { 
     return action; 
    } 

    public String getTask() { 
     return task; 
    } 
} 

要交換數據。沒有理由創建並解析String s。

1

如您使用的是內置的同步是​​從synchrnoization機制的「最慢」你沒降低您的代碼的性能。

您有一個完美的使用案例BlockingQueue。它爲您提供puttake操作,這些操作會阻止空格/元素可用。

ConcurrentLinkedQueue爲您提供只有線程安全不同步。這意味着您可以在多線程應用程序中安全地添加/刪除隊列中的元素,但它不提供等待空間/元素的機制,所以您已經正確使用了wait(),notify()方法(儘管您可以同步於任何其他共享對象,它不必是那個隊列)。在Java中使用Lock而不是synchronized更快。

+0

我想要一個同步塊的主要原因是因爲我希望對代碼的操作部分以原子方式執行。 –

+0

我不知道你的意思是要求你的部分代碼,我沒有看到這樣的事情。 BlockingQueue add()完全實現了這部分代碼:while(queue.size()> = 8) queue.wait(); queue.add(action +「#」+ task); queue.notifyAll();但以更高效的方式 – Zielu

-2

假設produceconsume將獨立調用,你可能會結束了一個無限循環,因爲這兩個試圖鎖定隊列對象,因此一旦consume沒有找到它永遠不會釋放鎖防止產生任何元素從不斷增加的元素。同步邏輯可能應該在調用consumeproduce的方法中實現。

+0

它們釋放了等待()操作中的鎖。 – Zielu

+0

你是對的,錯過了等待...... – kpentchev

相關問題