2013-08-02 27 views
3

可變數據我有這個線程我的項目在其內部運行的汽車無接受新符號訪問私有訪問來自不同類

public class StreamThread extends Thread { 
    private Set<String> allSymbolSet = new HashSet<String>(Arrays.asList("USBC", "TCSD", "PCLJ")); 
    private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>(); 

    public void addSymbols(String str) { 
     if (str != null) { 
      priorityBlocking.add(str); 
     } 
    } 

    public void run() { 
     while (true) { 
      try { 
       while (priorityBlocking.peek() != null) { 
        String symbol = priorityBlocking.poll(); 
        allSymbolSet.add(symbol); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

我的問題是,我想從另一個類

訪問變量allSymbolSet什麼會以訪問這個變量從anoter類名爲allSymbolSet最好的方法,爲了這個,我有兩個選擇

  1. 將allSymbolSet的訪問說明符從private修改爲default。

  2. 寫這supoused返回集

請建議我一個GET方法,這將是在這種情況下,好的方法?

+1

更可能2,但*爲什麼*其他類試圖訪問'allSymbolSet',它想用它做什麼? – Joni

回答

2

幾點意見:

  • 如果您所設定的非私有,一些代碼可以修改它(錯誤地或故意的),這可能會導致您的StreamThread類不一致的行爲。不要這樣做。
  • 提供一個簡單的getter並不能解決上述問題。更喜歡返回你的設置的副本。
  • 在多線程環境中,儘可能使變量保持最終狀態 - 它解決了許多線程安全問題。
  • 使用synchronizedSet甚至更​​好的通過包裝一個ConcurrentHashMap通常提供更好的性能比身高擴展Thread
  • 實現Runnable您將需要同步所有訪問您的設置(讀寫),例如。
  • ,而不是peek + poll你可以從你的隊列

簡單take所以你的最後一類可能看起來像:

public class StreamTask implements Runnable { 

    private final Set<String> allSymbolSet; 
    private final PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>(); 

    public StreamTask() { 
     String[] symbols = {"USBC", "TCSD", "PCLJ"}; 
     //use a thread safe set, for example based on ConcurrentHashMap 
     allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); 
     Collections.addAll(allSymbolSet, symbols); 
    } 

    public void addSymbols(String str) { 
     if (str != null) { 
      priorityBlocking.add(str); 
     } 
    } 

    public Set<String> getSymbols() { 
     return new HashSet<> (allSymbolSet); //return a copy 
    } 

    public void run() { 
     while (true) { 
      try { 
       allSymbolSet.add(priorityBlocking.take()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

最後,我可能失去了一些東西,但是那類看起來相當於更簡單:

public class StreamTask { 

    private final Set<String> allSymbolSet; 

    public StreamTask() { 
     String[] symbols = {"USBC", "TCSD", "PCLJ"}; 
     //use a thread safe set, for example based on ConcurrentHashMap 
     allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); 
     Collections.addAll(allSymbolSet, symbols); 
    } 

    public void addSymbols(String str) { 
     if (str != null) { 
      allSymbolSet.add(str); 
     } 
    } 

    public Set<String> getSymbols() { 
     return new HashSet<> (allSymbolSet); //return a copy 
    } 
} 
+0

+1返回的設置,很高興回答時也創建副本。 –

+0

如果我使用final關鍵字,不會允許它來修改設置和PriorotyBlockingQueue ?? – Kiran

+1

@Kiran你可以添加到最終設置或從最終設置中刪除,但不能重新分配。所以你不能寫:'allSymbolSet = new HashSet <>()'在構造之後。 – assylias

3

最好的辦法是getter方法和同步這樣的訪問對象allSymbolSet,東西:

public Set<String> getAllSymbolSet() { 
    synchronized(allSymbolSet) { 
     return allSymbolSet; 
    } 
} 

,並同步你的線程內訪問allSymbolSet

+0

爲什麼它更好? –

+0

非常感謝,但爲什麼我需要同步?在這種情況下是否需要synchrnozation? – Kiran

+1

是的,因爲你將有兩個線程訪問相同的HashSet,HashSet不是線程安全的 – morgano

0

更好的方法是方法2.寫一個getter方法。如果你想允許設置值,那麼稍後再使用setter。然後你的數據將被封裝。

0

編寫一個應該返回Set的get方法。通過使用這個你的私人仍然是私人的,你也可以使用同一個類的對象從外部訪問它。