2012-04-17 37 views
1

我有類SpeexRunner如下,構造函數接受兩個參數一個布爾變量和LinkedList<short[]>。具體如下: -將LinkedList <short[]>傳遞給構造函數,它會工作嗎?

public class SpeexRunner implements Runnable { 
    public boolean stopThread; 
    LinkedList<short[]> dataList; 

    public SpeexRunner(boolean val_stopThread, LinkedList<short[]> dataRef){ 
     this.stopThread = val_stopThread; 
     dataList = dataRef; 
    } 
    @Override 
    public void run() { 
    //add objects in dataList; 
    // change/remove dataList Objects 
    } 
} 

我的問題是: - 如果我改變DataList控件運行()內,將變化反映到被宣告別的地方原來的名單?

+0

注:鏈表不是線程安全的。如果您在另一個線程中調用run(),則可能會看到或不會看到對集合所做的更改。 – 2012-04-17 11:45:05

回答

5

如果我更改run()中的dataList,那麼這些更改是否會反映到在其他地方聲明的原始列表中?

是的。您的構造函數將參考收到列表中,而不是它的副本。如果你想複製它,你必須使用LinkedListcopy constructor。然後您將擁有自己的副本。但請注意,兩個列表中的條目仍然是共享的,因爲條目是數組(short[]),並且數組按引用存儲。

import java.util.*; 

public class ListExample { 
    public static final void main(String[] args) { 
     List<short[]> list; 

     // Direct use (no copies) 
     list = new LinkedList<short[]>(); 
     list.add(new short[] { 0, 0, 0 }); 
     System.out.println("list.size() before direct use: " + list.size()); 
     System.out.println("list.get(0)[0] before direct use: " + list.get(0)[0]); 
     new DirectUser(list).doSomething(); 
     System.out.println("list.size() after direct use: " + list.size()); 
     System.out.println("list.get(0)[0] after direct use: " + list.get(0)[0]); 
     // Output, note how both the list and its contents have been changed: 
     // list.size() before direct use: 1 
     // list.get(0)[0] before direct use: 0 
     // list.size() after direct use: 2 
     // list.get(0)[0] after direct use: 1 

     // Copying the list, but note that the entries are shared by both lists: 
     list = new LinkedList<short[]>(); 
     list.add(new short[] { 0, 0, 0 }); 
     System.out.println("list.size() before copy-list use: " + list.size()); 
     System.out.println("list.get(0)[0] before copy-list use: " + list.get(0)[0]); 
     new CopyListUser(list).doSomething(); 
     System.out.println("list.size() after copy-list use: " + list.size()); 
     System.out.println("list.get(0)[0] after copy-list use: " + list.get(0)[0]); 
     // Output, note how our list didn't change (it doesn't have a new entry), but 
     // the entry at index 0 *was* changed: 
     // list.size() before copy-list use: 1 
     // list.get(0)[0] before copy-list use: 0 
     // list.size() after copy-list use: 1 
     // list.get(0)[0] after copy-list use: 1 

     // "Deep" copying, both the list and its entries: 
     list = new LinkedList<short[]>(); 
     list.add(new short[] { 0, 0, 0 }); 
     System.out.println("list.size() before deep-copy use: " + list.size()); 
     System.out.println("list.get(0)[0] before deep-copy use: " + list.get(0)[0]); 
     new DeepCopyUser(list).doSomething(); 
     System.out.println("list.size() after deep-copy use: " + list.size()); 
     System.out.println("list.get(0)[0] after deep-copy use: " + list.get(0)[0]); 
     // Output, note that neither the list nor its entries was affected by the call: 
     // list.size() before deep-copy use: 1 
     // list.get(0)[0] before deep-copy use: 0 
     // list.size() after deep-copy use: 1 
     // list.get(0)[0] after deep-copy use: 0 


     System.exit(0); 
    } 

    static class DirectUser { 
     List<short[]> items; 

     DirectUser(List<short[]> items) { 
      // DirectUser doesn't copy the list 
      this.items = items; 
     } 

     void doSomething() { 
      this.items.get(0)[0] = 1; 
      this.items.add(new short[] { 2, 2, 2 }); 
     } 
    } 

    static class CopyListUser { 
     List<short[]> items; 

     CopyListUser(List<short[]> items) { 
      // CopyListUser copies the list, but both lists still share items 
      this.items = new LinkedList<short[]>(items); 
     } 

     void doSomething() { 
      this.items.get(0)[0] = 1; 
      this.items.add(new short[] { 2, 2, 2 }); 
     } 
    } 

    static class DeepCopyUser { 
     List<short[]> items; 

     DeepCopyUser(List<short[]> items) { 
      // DeepCopyUser copies the list AND each entry 
      this.items = new LinkedList<short[]>(); 
      for (short[] entry : items) { 
       this.items.add(Arrays.copyOf(entry, entry.length)); 
      } 
     } 

     void doSomething() { 
      this.items.get(0)[0] = 1; 
      this.items.add(new short[] { 2, 2, 2 }); 
     } 
    } 
} 

DirectUser使用的名單中,我們調用的代碼中,我們看到了雙方的名單變化(因爲它有更長的時間),並對其內容(第一:

這也許是最好的例子證明入口的第一個槽從0更改爲1)。

CopyListUser使用它時,它做了一個拷貝的列表,所以我們在調用代碼中沒有看到我們列表的任何變化(它沒有變長)。但我們確實看到更改爲第一項(因爲這兩個列表共享相同的陣列對象)  —第一個插槽再次從0更改爲1

DeepCopyUser使用它,它做了一個複製列表每個條目的副本,這樣的事情是完全徹底的分離。我們的呼叫代碼沒有看到對列表或其項目的更改。

2

是的,它將作爲線程對列表的引用,而不是列表的副本。需要注意的是LinkedList不同步

如果多個線程同時訪問一個鏈接列表,並在線程中的至少一個結構上修改了列表,它必須保持外部同步。

3

如果我改變的run()內的數據列表,將在變化反映到被宣告別的地方原來的名單?

簡答:是的。

稍微長一點的答案:是的,因爲參數總是通過Java中的引用傳遞。(可能你會使用LinkedList的(假設)子類來禁止或忽略更改,在這種情況下,嘗試的更改會導致異常或不起作用,但這是不正當的。 ..)

+0

謝謝.. @Stephen C. – aProgrammer 2012-04-17 12:02:49

2

如果添加元素/從列表中刪除元素,改變將是你的代碼的其餘部分可見。請注意,如果您使用多個線程,則需要使用同步來確保更改可見。

如果在另一方面,你不想改變,才能擺脫你的類,你可以創建你的構造一個新的列表,並添加原始列表中的所有項目。在這種情況下,對列表的更改將不會從外部看到,但是如果對列表中的項目進行更改,則會發生這些更改。

相關問題