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在迭代它时不会对其进行修改。将其设为同步地图是否可以保证这种行为?还是我需要synchronized声明。同步语句的行为会像我期望的那样吗?

谢谢

4

4 回答 4

5

您需要synchronized循环周围的块。

有关详细信息,请参阅JavaDoc

于 2010-10-08T05:39:20.710 回答
2

是的,您拥有的同步语句将像您期望的那样工作。我只想添加一条评论,您正在接受套接字连接的线程将阻塞 registry.put(id, serverThread); 当您在另一个线程的同步部分时。这意味着您的服务器在处理通知时不会处理任何新的传入请求......

您可能需要考虑将 put 语句(当然将 serverThread 更改为此)移动到 ServerThread 的 run 方法的 run 方法的第一行。这样,如果 callSomePublicMethodOnThread 最终需要很长时间来处理,您就不会阻止传入的连接。

于 2010-10-08T06:13:44.610 回答
1

为了让一切更容易,我会使用 ConcurrentHashMap (http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html) 所以你不需要使用同步块在循环中,因为 concurrentHashMap 使用了不同类型的迭代器(不是快速失败的迭代器)并且它不会抛出 concurrentModificationException,你也会有更好的性能。

于 2010-10-08T09:57:08.890 回答
0

代码中有一个问题,您不能将您的方法定义为“private void notify()”,因为“notify()”是在 Object 类中定义的方法

于 2012-02-28T13:54:49.487 回答