假设我有这样的课程:
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
声明。同步语句的行为是否与我期望的一样?
由于
答案 0 :(得分:5)
循环周围需要synchronized
块。
有关详细信息,请参阅JavaDoc。
答案 1 :(得分:2)
是的,你所拥有的同步语句将像你期望的那样工作。我只想添加一条注释,你接受套接字连接的线程将阻塞在registry.put(id,serverThread);当你在另一个线程的同步部分。这意味着您在处理通知时服务器不会处理任何新的传入请求.....
您可能需要考虑移动put语句(当然将serverThread更改为此) 到ServerThread的run方法的run方法的第一行。这样,如果callSomePublicMethodOnThread需要花费很长时间来处理,你就不会阻止传入连接。
答案 2 :(得分:1)
为了让一切变得简单,我将使用ConcurrentHashMap(http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html),因此您无需使用循环中的同步块,因为concurrentHashMap使用不同类型的迭代器(不是故障快速迭代器),并且它不会使并发兼容更改,你也会有更好的性能。
答案 3 :(得分:0)
代码中存在一个问题,您无法将方法定义为“private void notify()”,因为“notify()”是Object类中定义的方法