8
回答
hashTable 和 hashMap 作缓存,实现的两种单例的区别
终于搞明白,存储TCO原来是这样算的>>>   

看过不同的源码,可还是不太懂下面两种数据结构实现的单例有什么区别:

// 第一种使用 hashtable
private static Hashtable<String, StringManager> managers = new Hashtable<String, StringManager>();
// 第二种,使用 hashmap
//	private static Map<String, StringManager> managers = new HashMap<String, StringManager>();
public synchronized static StringManager getManager(String packageName) {
	StringManager manager = managers.get(packageName);
	if (manager == null) {
		manager = new StringManager(packageName);
		managers.put(packageName, manager);
	}
	
	return manager;
}



不知道,使用 hashMap 和 hashTable ,在程序的使用上会有什么区别??

个人认为,因为使用 synchronized 同步,感觉两种实现应该是一样的。不过我知道这种理解有一定的错误,所以特意来问一下大家的。

使用 hashMap 会引起并发问题吗??


举报
静心天涯
发帖于3年前 8回/1K+阅

以下是问题补充:

  • @静心天涯 :还有另外一种实现 ConcurrentHashMap,这些实现之间有什么区别呢?? (3年前)
共有8个答案 最后回答: 3年前
hashMap和 hashTable区别主要是hashTable对所有的读取和修操作改加了同步锁,你的那个例子如果没有其他入口可以修改managers的情况下 hashMap和 hashTable是一样的,否则会有并发问题, ConcurrentHashMap主要是用了分段锁,并发使用性能好点,可以看下源代码就知道了
--- 共有 2 条评论 ---
rookiefly回复 @静心天涯 : 你的manager获取,判断,修改managers这个过程不是原子操作,如果不加锁还是会有并发问题,比如你不加锁,第一个线程在判断manager之后,cpu切换到了另一个同样的操作该方法的线程,会导致并发问题出现。 3年前 回复
静心天涯谢谢,看过 Javadoc,知道ConcurrentHashMap同步了读和写操作。另外我还是比较好奇的是:(上述代码在其他地忙没有不能修改 managers),如果在上述代码里使用 ConcurrentHashMap,那对应的在 getManger 方法是否可以不加锁 sync? 3年前 回复

引用来自“红薯”的评论

担心多线程的话就 Hashtable 了

想不出来会有并发问题,这sync static是在类上加的锁。
--- 共有 1 条评论 ---
静心天涯个人认为两个实现应该是一样的,如果 hashTable 是同步的,是否意味着可以不用 sync 锁;如果是用 hashMap,就需要加锁。不过这些都是看源码学来的,感觉人家这么用,应该有其原因所在,不过我不知道而已。上述代码是在 tomcat 源码找到的,在其他源码上,我也见过这些做法。 3年前 回复

引用来自“东胜神洲”的评论

如果不是一定要运行在  jdk1.4 以下的。。为毛不使用  ConcurrentHashMap 呢?

说细一点,如果你希望用来做本地缓存(特别是写少读多的环境下)的话,ConcurrentHashMap 能够提供更高的性能(相对加锁),特别是到了 JDK8 ,ConcurrentHashMap 越倾向于本地缓存的利器。。。当然,你对性能要求不高,反而追求很高的一致性,使用HashMap或 HashTable 是没什么问题的。。。。

深入延续可读: http://my.oschina.net/adan1/blog/158149   了解一致性问题。


使用hashtable至少可以解决通过反射直接操作managers带来的同步问题
通过反射取得private static HashMap或HashTable的示例代码, 写得很丑,轻拍。

public class Main {
    public static void main(String args[]){
        try {
        	  Field f = Test.class.getDeclaredField("mgrs"); 
              f.setAccessible(true);
              HashMap<String,String> foo  = (HashMap<String,String>)f.get(null);
              foo.put("key", "I put this key with java reflection.");
              System.out.println(Test.get("key"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class Test{
    private static HashMap<String,String> mgrs = new HashMap<String, String>();
    private Test(){
    }
    public synchronized static String get(String str){
    	return mgrs.get(str);
    }
}




顶部