2016-12-21 82 views
1

我正在嘗試編寫一個具有多個線程的Java程序。我有兩個在啓動時創建的變量。一個是AtomicBoolean,它告訴整個程序何時關閉(即關閉客戶端)。另一個變量是一個ConcurrentHashMap,它包含一組在啓動時加載的命令。有一些線程包含客戶端可運行的客戶端已被接受(每個客戶端一個線程)運行。還有一個線程通過監聽外部變化更新命令到HashMap中(從目錄的新命令等)與併發共享變量

這裏是代碼:

class Program { 
    /* ... other vars like ServerSocket, etc. */ 
    private final ConcurrentHashMap<String, String> mCommands; 
    private final AtomicBoolean mIsListening; 

    public static void main(String[] args) { 
     Program prog = new Program(); 
     prog.loadCommands(); 
     prog.listen(); 
    } 

    public Program() { 
     mCommands = new ConcurrentHashMap<>(); 
     mIsListening = new AtomicBoolean(true); 
     /* other initializations */ 
    } 

    public void loadCommands() { 
     /* Loads commands generated from a directory; updates mCommands, then... */ 
     new Thread(new CommandListenerRunnable(mCommands)).start(); 
    } 

    public void listen() { 
     /* accepting a new client from server socket */ 
     while (mIsListening.get()) { 
      Socket client = ss.accept(); 
      new Thread(new ClientRunnable(client, mCommands, mIsListening)).start(); 
     } 
    } 
} 

正如你所看到的,每我正在創建的孩子,我將這些變量作爲參數傳遞。總而言之,這是分配這些變量的正確方法嗎?任何想法將不勝感激。提前致謝!

+1

保持對字段的控制並僅傳遞對this的引用可能更安全。 – shmosel

+0

@shmosel謹慎地在答案中詳細說明,如果它足夠,我會將其標記爲正確的?嘗試瞭解如何在Runnables的上下文中使用對此的引用。 – Zack

回答

3

我認爲設計很好,因爲每個線程都應該有它需要的變量的副本。

你說:

例如,我可以使用map.putIfAbsent()使被原子進行

操作,但這並不能使你的地圖線程安全的,因爲有人可能會調用還有其他的東西。

+0

謝謝您的設計輸入。至於第二部分,我明白你在說什麼,如果我們正在討論一個常規的HashMap。但是,我認爲ConcurrentHashMap背後的重點是通過允許對它進行原子讀取和寫入來使線程安全。 – Zack

+1

您可以在這裏看到:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html ConcurrentHashMap實現了Map接口,因此它可以獲得像put等所有的地圖功能。 ...查看API以瞭解哪些方法和原因不是原子的。 – ddarellis

2

嗯,這不是萬無一失的。閱讀的ConcurrentHashMap的文檔中的所有caveats這樣as--

「的彙總狀態的方法,包括大小,的isEmpty和 中的containsValue通常是有用的,只有當一個地圖沒有發生在其他線程 併發更新的結果「。

如果這些限制是可以接受的,那麼你有什麼好。否則,您將需要您自己的鎖定方案來管理訪問。

它可能是一樣簡單的synchronized(sharedLockingObject),或者像ReentrantReadWriteLock一樣複雜。

+1

有很多警告。但是,我不認爲這是我遇到問題的同步部分。例如,我可以使用map.putIfAbsent()使操作以原子方式執行。我只是更關心我的設計選擇是否以正確的方式傳遞這些變量。 – Zack

+0

@解決方法1:聽起來好像您可能正在通過傳遞自己的布爾值來重新創建線程中斷機制來達到相同的目的?但是,我沒有看到任何設計缺陷。 –

+0

這是真的。但是,它要麼使用全局變量來關閉它們,要麼必須存儲每個客戶端的引用以調用每個子進程的中斷。但是非常感謝你的所有意見。 – Zack