2011-01-24 40 views
2

我试图开发一个程序,它接收存储在地图中的数据请求。地图在主方法中声明,如下所示:在主线程中创建并传递到新线程的地图对象的正确同步

Map m = Collections.synchronizedMap(new HashMap()); 
synchronized(m) { 
     while (listening) { 

      new BrokerLookupServerHandlerThread(serverSocket.accept(), m).start(); 

     } 
} 

用于BrokerLookupServerHandlerThread代码获取输入,并且使得对象的变量之一。如果我在这堂课中使用它,原始地图是否也会更新?我明白Java是通过价值传递的,(我习惯于C/C++),所以我只是想确定这个同步对象的实现是否有意义。

private Socket socket = null; 
//private String t ="MSFT"; 
public Map m; 

public BrokerLookupServerHandlerThread(Socket socket, Map m) { 
    super("NamingServerHandlerThread"); 
    this.socket = socket; 
    this.m = m; 
    System.out.println("Created new Thread to handle client"); 
} 

感谢您的帮助。

+0

对于原始地图正在更新的问题,我建议您自己尝试一下,看看会发生什么。没有必要在理论层面上进行这种讨论:) – 2011-01-24 08:23:17

回答

1

是原始对象将被更新。不过,我建议你使用ConcurrentHashMap

的哈希表支持检索的完全并发 和 更新 期望可调整并发。该类遵循与Hashtable 相同的功能规范,并且包括对应于每个方法 Hashtable的方法版本 。但是,即使所有操作都是线程安全的, 检索操作不会导致锁定,也不支持以阻止所有访问的方式锁定整个表 。 本课程完全与 可互操作的程序依赖其 线程安全性,但不依赖其 同步详细信息。

+0

感谢您的建议。您能否扩展为什么在这种情况下建议使用ConcurrentHashMap? – Kaigi 2011-01-24 07:44:46

1

是的,两个线程都会看到对地图所做的更改。

Java确实使用按值传递 - 但在这种情况下,值是引用(类似于指针)。 Java中引用类型变量的值是总是对对象的引用,或者为null。它从来不是对象本身。

所以你的代码不会创建一个新的地图。有很少的操作隐含地创建一个新的对象。我只能想到使用字符串文字(无论如何都是文字的实现)和原始类型的自动装箱。除此之外,您只会通过new操作员获得一个新对象。 (显然你调用的任何方法也可能会创建一个新的对象...)

请注意,这是完全分开的问题同步之间的线程。有关复制对象与复制参考的业务与线程正交。在这种情况下,您看起来像使用Collections.synchronizedMap解决了线程方面的问题;因为Pangea说你可能想要使用ConcurrentHashMap,而不会使用几乎一样多的锁定(如果有的话)。 ConcurrentMap接口的另一个实现是ConcurrentSkipListMap。查看这两个课程的文档,以决定最适合您的内容。

+0

感谢您澄清在Java中如何传递价值! – Kaigi 2011-01-24 07:45:43

相关问题