0

假設我有一個這樣的類:在這種情況下,同步語句如何工作?

public class Server { 

    public static void main(String[] args) { 

     Map<Integer, ServerThread> registry = Collections.synchronizedMap(new LinkedHashMap<Integer, ServerThread>()); 

     ... 

     while(true) { 
     Socket socket = serverSocket.accept(); 
     ServerThread serverThread = new ServerThread(id, registry); 
     registry.put(id, serverThread); 
     } 
    } 
} 

然後:

public class ServerThread extends Thread { 

    private Map<Integer, ServerThread> registry; 
    private int id; 

    public ServerThread(int id, Map<Integer, ServerThread> registry) { 
     this.id = id; 
     this.registry = registry; 
    } 

    ... 

    private void notify() { 
     synchronized(registry) { 
     for(ServerThread serverThread : registry.values()) { 
      serverThread.callSomePublicMethodOnThread(); 
     } 
     }  
    } 
} 

我只是想確保,而我遍歷它registry並未修改。使它成爲同步映射可以保證這種行爲嗎?或者我需要​​聲明。同步語句的行爲是否像我期望的那樣?

感謝

回答

5

您需要周圍的環路​​塊。

查看JavaDoc瞭解詳情。

+0

感謝的方法! (必填字符) – 2010-10-08 06:07:05

2

是的,您擁有的同步語句將按照您的預期工作。我只是添加一個評論,你接受套接字連接的線程將阻止在registry.put(id,serverThread);而您在另一個線程的同步部分。這意味着你的服務器將不會處理任何新的傳入請求,而你正在處理通知.....

你可能想考慮移動put語句(當然改變serverThread到這個) 到第一行ServerThread運行方法的運行方法。這樣,如果callSomePublicMethodOnThread需要很長時間來處理,您將不會阻止傳入的連接。

+0

好點!我剛剛發佈了一個簡化的例子。在我的實際代碼中,我在循環中引發了單獨的線程,因此實際的處理在這些線程中完成。但你說得很好。我會移動它!謝謝! – 2010-10-08 16:57:07

1

爲了使一切更容易,我會使用ConcurrentHashMap(http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html),所以你不需要使用循環中的同步塊,因爲concurrentHashMap使用不同類型的迭代器(而不是快速迭代器),並且不會導致concurrentModificationException,您也將獲得更好的性能。

0

有代碼的一個問題,你不能定義你的方法是「私人無效通知()」,因爲「通知()」是在Object類中定義

相關問題