2013-04-14 61 views
0

如何在使用兩個線程時確保打印輸出順序與原始數組中的順序相同?我想打印'0 1 2 3 4 5 6 7 8 9',但目前的訂單不能保證。有什麼辦法可以做到這一點?萬分感謝。在多個線程中維護Arraylist的順序

public class Test { 
    public static void main(String[] args){ 
     DataStore dataStore = new DataStore(); 
     for(int i=0; i<10; i++){ 
      dataStore.add(String.valueOf(i)); 
     } 
     CopyThread t1 = new CopyThread(dataStore); 
     CopyThread t2 = new CopyThread(dataStore); 
     t1.start(); 
     t2.start(); 

     try { 
      t1.join(); 
      t2.join(); 
     } catch(Throwable t) { 
     } 
    } 
} 

class CopyThread extends Thread { 
    private DataStore data; 

    public CopyThread(DataStore data){ 
     this.data = data; 
    } 
    public void run(){  
     DataStore.Line line = null; 
     int lineID; 

     while((line = data.getLine()) != null){  
      lineID = line.id;  
      System.out.println(Thread.currentThread().getName() + ": " + lineID);  
     } 
    } 
} 

class DataStore { 
    ArrayList<String> lines = new ArrayList<String>(); 
    int current = 0; 

    public synchronized Line getLine() { 
     if (current >= lines.size()) { 
      return null; 
     } 
     Line line = new Line(lines.get(current), current); 
     current++; 

     return line; 
    } 

    public synchronized void add (String s) { 
     lines.add(s); 
    } 

    public synchronized int size() { 
     return lines.size(); 
    } 

    public static class Line { 
     public String line; 
     public int id; 

     public Line (String str, int i) { 
      line = str; 
      id = i; 
     } 
    } 
} 

回答

1

嘗試向量而不是ArrayList。

Vector

Vector類可以實現可增長的對象陣列。與 陣列一樣,它包含可以使用整數 索引訪問的組件。但是,矢量的大小可根據需要增大或減小,以便在創建矢量 後適應添加和刪除項目。

每個載體都嘗試通過維護容量和capacityIncrement來優化存儲管理。容量總是至少與矢量大小一樣大;它通常會更大,因爲隨着組件 被添加到矢量中,矢量的存儲量將以容量增量的大小增加。在插入大量組件之前,應用程序可以增加矢量的容量;這減少了增量重新分配的數量。

由Vector的iterator和listIterator方法返回的迭代器 是快速失敗的:如果載體是隨時 通過 迭代器自身的remove結構上修改迭代器創建後,以任何方式,除了或add方法,該迭代器將拋出一個 ConcurrentModificationException。因此,面對併發的修改,迭代器快速且乾淨地失敗,而不是在將來確定時間 處冒着任意的,非確定性行爲的風險。 Vector元素方法 返回的枚舉不是快速失敗。

請注意,迭代器的故障快速行爲無法保證,因爲通常情況下,在存在非同步併發修改的情況下,無法保證 。迭代器在盡力而爲 的基礎上拋出ConcurrentModificationException時出現快速失敗 。因此,編寫一個依賴於此例外的 的程序是錯誤的,因爲它的正確性: 迭代器的故障快速行爲應僅用於檢測錯誤。

+0

同樣的,向量,當然 – user697911

0

您可以使用同步來實現這一目標:

synchronized(data) { 
    while((line = data.getLine()) != null){  
     lineID = line.id;  
     System.out.println(Thread.currentThread().getName() + ": " + lineID);  
    } 
} 
+0

的我測試過,但後來就變成了單線程程序,只有一個線程使用,如果數據是同步的。 – user697911

+0

它不會是一個單線程程序。你看到它,因爲你的程序沒有其他任何事情要做。如果你添加多個功能併產生更多的線程,你會看到。肯定t2不能做任何事情,因爲t1已經持有鎖,這就是爲什麼你看到了這種行爲。 –

+0

但我想要的是t1和t2都處理DataStore對象,以加快我的應用程序。 while循環將會比我在這裏顯示的要多。但這足以說明問題。 – user697911