2010-07-26 75 views
2

我需要ArrayList中的幫助。 我有一個字符串arraylist。我正在循環訪問這個列表並將它們一個接一個地發送到輸出流。 當我在列表中循環併發送它們時,另一個線程可能會向它添加一些元素。發送一個元素後,它也必須從列表中刪除。如何通過多線程成功訪問和循環ArrayList?

我該如何做到這一點?

回答

9

如果項目被添加到列表的末尾,您最好使用Queue來代替。 Java5及以上版本提供了多種線程安全實現,包括ConcurrentLinkedQueueLinkedBlockingQueue

一般來說,前者是最好的選擇,除非你想要一個有界的阻塞隊列,在這種情況下使用後者。

+1

的'ArrayBlockingQueue'是不是真的合適,因爲它是一個固定大小的集合(即其容量後不能改變施工)。 – BalusC 2010-07-26 15:33:04

+0

@BalusC,在你輸入你的評論時只修復了一個:-) – 2010-07-26 15:35:40

+0

很有趣,看看它是如何得到更多的upvotes,因爲它是在一分鐘前發佈的,而你在我回答之後只需一分鐘就快速編輯了'ConcurrentLinkedQueue' :) – BalusC 2010-07-26 15:54:12

6

爲作業使用正確的數據結構。使用ConcurrentLinkedQueue。以下是它在javadoc中的描述:

基於鏈接節點的無限線程安全queue。該隊列命令元素FIFO(先進先出)。隊列中的是已在隊列上最長時間的元素。隊列中的尾部是已經在隊列上的最短時間的元素。新元素插入到隊列尾部,隊列檢索操作獲取隊列頭部的元素。 當許多線程共享對一個通用集合的訪問時,A ConcurrentLinkedQueue是一個合適的選擇。

+1

應該知道ConcurrentLinkedQueue不等待隊列不爲空。含義任何輪詢將在LinkedBlockingQueue等待輪詢時返回null。不確定OP要求哪個。 – 2010-07-26 16:34:37

0

假設這是作業,我會給出一些提示。

  • 兩個線程可以synchronize名單上保留獨佔訪問
  • remove()方法返回的對象中刪除
  • 您可以從列表的開始同時加入到結束

刪除這應該可以幫助你,如果你發佈了迄今爲止的所有內容,那麼我們可以根據你的代碼提供建議。

2

我建議使用的BlockingQueue的一些執行情況的ArrayList是不適合併發修改:

class Producer implements Runnable { 

    private BlockingQueue<String> queue; 

    public Producer(BlockingQueue<String> queue) { 
    this.queue = queue; 
    } 

    public void run() { 
    try { 
     queue.put("foo"); 
     queue.put("done"); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

class Consumer implements Runnable { 

    private final BlockingQueue<String> queue; 

    public Consumer (BlockingQueue<String> queue) { 
    this.queue = queue; 
    } 

    public void run() { 
    try { 
     String value = queue.take(); 
     while (!value.equals("done")) { 
     value = queue.take(); 
     System.out.println(value); 
     } 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

public class Main { 
    public static void main(String[] args) throws Exception { 
    BlockingQueue<String> queue = new LinkedBlockingQueue<String>(); 
    Thread producer = new Thread(new Producer(queue)); 
    Thread consumer = new Thread(new Consumer(queue)); 
    producer.start(); 
    consumer.start(); 
    producer.join(); 
    consumer.join(); 
    } 
} 
+0

感謝大家的所有回覆 – kap 2010-07-26 15:53:32

+0

不錯的演示代碼。 – 2010-07-26 15:54:05