`
Norther
  • 浏览: 26381 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Google Collections(Guava)中强大的Concurrent MapMaker

阅读更多
仔细研究了刚发布1.0版本的Google Collections,被其中的MapMaker震惊,这不就是我梦寐以求的Concurrent Map神器吗?如果Google Collection在5年前就发布该有多好?!废话少讲,邀请大家一起来观赏一下什么是MapMaker。

Hashtable太老土啦,线程安全我都用ConcurrentHashMap。什么?现在流行MapMaker?

JDK 1.5引入的ConcurrentHashMap由于其精巧的设计,更高的并发性能,捕获了大家的心,在并发场景中出场率极高,但随着深入的使用,很快的就发现了其中的不足。例如在以Map作为Cache的典型场景中,我们都需要有元素过期的处理,WeakHashMap是这方面的高手,但其在并发方面有点菜(非线程安全),当我们想让这两位大将同时上场的时候,就只能抓耳搔腮了。

Google Collections中的MapMaker融合了Weak Reference,线程安全,高并发性能,异步超时清理,自定义构建元素等强大功能于一身。(注)

常阅读优秀源代码的童鞋都知道,一般叫Maker的对象都是Builder模式,而这个MapMaker就是来"Build"Map的,下面的代码展示了如何构建一个高并发性能,线程安全的WeakHashMap.

	public void testWeakKeys() throws Exception {
		ConcurrentMap<Key, Value> map = new MapMaker()
			.weakKeys() // 指定Map保存的Key为WeakReference机制
			.makeMap(); 

		Key key = new Key();
		map.put(key, new Value()); // 加入元素
		key = null; // key变成了WeakReference

		System.gc();// 触发垃圾回收
		TimeUnit.SECONDS.sleep(1L);

		assertTrue(map.isEmpty()); // map空了,因为WeakReference被回收
	}

是不是够简单?他不仅支持WeakKeys,还支持WeakValues。
	public void testWeakValues() throws Exception {
		ConcurrentMap<Key, Value> map = new MapMaker()
			.weakValues() // 指定Map保存的Value为WeakReference机制
			.makeMap(); 

		Key key = new Key();
		Value value = new Value();
		map.put(key, value); // 加入元素
		key = null; // Key成了WeakReference
		
		System.gc();// 触发垃圾回收
		TimeUnit.SECONDS.sleep(1L);
		
		assertFalse(map.isEmpty()); // map里的东西还在,因为Value还是StrongReference
		
		value = null; // 这次value也变成了WeakReference

		System.gc(); // 触发垃圾回收
		TimeUnit.SECONDS.sleep(1L);

		assertTrue(map.isEmpty()); // map真空了,因为Value是WeakReference被回收
	}


还可以选用SoftKeys,和SoftValues,随意组合,比只能WeakKey的WeakHashMap扩展性强太多了。

再来看看On-demand value computation,自定义构建元素。想象下面的场景,你要为一个查询学生信息的DAO增加结果缓存,并且结果超过60秒过期,我们可以用装饰模式结合MapMaker简单的实现。

	interface StudentDao {
		Information query(String name);
	}
	
	class StudentDaoImpl implements StudentDao {
		// 真正去查数据库的实现类 代码省略
	}
	// 装饰器
	class CachedStudentDao implements StudentDao {
		private final StudentDao studentDao;
		private final ConcurrentMap<String, Information> cache;

		public CachedStudentDao(final StudentDao studentDao) {
			Preconditions.checkNotNull(studentDao, "studentDao");
			this.studentDao = studentDao;
			
			this.cache = new MapMaker() // 构建一个 computingMap
				.expiration(60, TimeUnit.SECONDS) // 元素60秒过期
				.makeComputingMap(new Function<String, Information>(){
					@Override
					public Information apply(String name) {
						return studentDao.query(name);
					}
				});
				// 传入匿名Function自定义缓存的初始化。如果缓存中没有name对应的数据,则调用真正的dao去数据库查找数据,同时缓存结果。
		}

		@Override
		public Information query(String name) {
			return cache.get(name); // 从computing cache中取结果
		}
	}
	
	public void test() {
		StudentDao cachedStudentDao = new CachedStudentDao(studentDaoImpl);
		// 装饰了studenDaoImpl的cachedStudentDao具备了缓存结果的能力。
	}


线程安全,高并发性能,元素过期都实现了,并且代码很简洁。多亏了MapMaker,脏活、累活,就交给它啦。不过要注意的是,要遵循ConcurrentHashMap的规范,其不允许有Null的Key和Value。如果查询出来的结果可能为Null的,可用简单的包装类包装一下,这里不给出代码了。

怎么样?你是不是心动了呢?快下载来看看吧。

注:参考该文章了解是什么WeakReference?http://www.iteye.com/topic/401478
分享到:
评论
41 楼 Agrael 2010-05-22  
恩,目前正关注,等把相关资料看一遍再继续。
40 楼 Norther 2010-05-22  
Agrael 写道
我指的转正是纳入JDK API中。我个人不是很喜欢用非标准库里的东西,除非是正式的生产项目,是个怪癖。


可能并发包中的部分功能会被引入JDK 7,其他应该比较少,Google Collections就是正式的生产项目,它已经被广泛的使用在GMail,Google Reader,Blogger,Google Docs & Spreadsheets,AdWords,AdSense and dozens等等项目中,可以放心使用。(引自官方的FAQ,http://code.google.com/p/google-collections/wiki/Faq)
39 楼 Agrael 2010-05-22  
我指的转正是纳入JDK API中。我个人不是很喜欢用非标准库里的东西,除非是正式的生产项目,是个怪癖。
38 楼 Norther 2010-05-22  
Agrael 写道
其实我在想,google的collections什么时候转正。。。。。


已经转正了,09年12月30号发布的1.0正式版,我的项目里已经广泛使用了,而现在Google正在开发一个涉及面更广的类库,类似common-lang,叫Guava,并且会把Collections的内容全部包含进去,目前是RC4,状态很活跃,推荐大家关注。

http://code.google.com/p/guava-libraries/
37 楼 Agrael 2010-05-22  
其实我在想,google的collections什么时候转正。。。。。
36 楼 Norther 2010-05-22  
Agrael 写道
Norther 写道
Agrael 写道
Feiing 写道
Agrael 写道
Feiing 写道
Agrael 写道
private static final transient Map<Class<?>, CacheBeanInfo> CACHE_BEANINFO = new ReferenceMap<Class<?>, CacheBeanInfo>(ReferenceKeyType.WEAK,ReferenceValueType.SOFT);

自己写的一个ReferenceMap,封装了ConcurrentHashMap。
其实有时候自己多留意一下多用心,很多东西并不是不可能。
在使用开源包的时候,还是要自己思考下如果是自己的话该如何实现。不然真成了只会找开源的人了。


没仔细看你的代码, 但请允许我凭臆断说几句大言不惭的话

1. 我不认为你的实现会比 google-collections 优秀, 因为 :
2. 我不认为你的水平会比 Bob Lee 或者 Doug Lea 高

所以

3. 我会在项目里用公认的优秀类库而不会因为自己开心就写一些帮助不大的东西

因为

4. 这会导致项目的维护成本增加

如果我想让别人认可我的作品

5. 如果允许, 我会把它开源让所有的人来试用, 我会写一个 feature list comparison 来比较它跟其他作品, 代码放在那, 孰优孰劣大家心里都会很明白

另外 , 个人认为用中文写注释是一个非常坏的习惯



我并没说和什么相比,我只是说自己多留意一下多用心,很多东西并不是不可能。
我也没和google-collections比,当然我的水平没有 Bob Lee 或者 Doug Lea 高,但是,请先看明白我想说的是什么:)


楼主的主题是 google-collections MapMaker,  你上来就贴一个自己的类似实现, 如果这不是比较, 请问你想说什么?



貌似你不仅没看我写的东西,你还没仔细看楼主的回复就说了这些话,我那个是楼主说是否可以看看,我才发的。
在这之前,我只是想说明 自己多留意一下多用心,很多东西并不是不可能。 仅此而已。


仅此而已,就是仅表达了你认为“我没留意,我不用心”。但我这么起劲研究大牛代码的人,怎么就被你描述成不用心呢?


我也只是想借楼主的宝地说说我的那个想法,没想到伤到了楼主 ,道歉道歉。
不过,我觉得关于这个话题继续说下去,这个帖子就成水贴了,失去他原有的价值了,我们还是停吧?


停了,继续相关话题:
Google collections中猛料很多,推荐大家研究和使用,也可以在这里共同讨论,谢谢。
35 楼 Agrael 2010-05-22  
Norther 写道
Agrael 写道
Feiing 写道
Agrael 写道
Feiing 写道
Agrael 写道
private static final transient Map<Class<?>, CacheBeanInfo> CACHE_BEANINFO = new ReferenceMap<Class<?>, CacheBeanInfo>(ReferenceKeyType.WEAK,ReferenceValueType.SOFT);

自己写的一个ReferenceMap,封装了ConcurrentHashMap。
其实有时候自己多留意一下多用心,很多东西并不是不可能。
在使用开源包的时候,还是要自己思考下如果是自己的话该如何实现。不然真成了只会找开源的人了。


没仔细看你的代码, 但请允许我凭臆断说几句大言不惭的话

1. 我不认为你的实现会比 google-collections 优秀, 因为 :
2. 我不认为你的水平会比 Bob Lee 或者 Doug Lea 高

所以

3. 我会在项目里用公认的优秀类库而不会因为自己开心就写一些帮助不大的东西

因为

4. 这会导致项目的维护成本增加

如果我想让别人认可我的作品

5. 如果允许, 我会把它开源让所有的人来试用, 我会写一个 feature list comparison 来比较它跟其他作品, 代码放在那, 孰优孰劣大家心里都会很明白

另外 , 个人认为用中文写注释是一个非常坏的习惯



我并没说和什么相比,我只是说自己多留意一下多用心,很多东西并不是不可能。
我也没和google-collections比,当然我的水平没有 Bob Lee 或者 Doug Lea 高,但是,请先看明白我想说的是什么:)


楼主的主题是 google-collections MapMaker,  你上来就贴一个自己的类似实现, 如果这不是比较, 请问你想说什么?



貌似你不仅没看我写的东西,你还没仔细看楼主的回复就说了这些话,我那个是楼主说是否可以看看,我才发的。
在这之前,我只是想说明 自己多留意一下多用心,很多东西并不是不可能。 仅此而已。


仅此而已,就是仅表达了你认为“我没留意,我不用心”。但我这么起劲研究大牛代码的人,怎么就被你描述成不用心呢?


我也只是想借楼主的宝地说说我的那个想法,没想到伤到了楼主 ,道歉道歉。
不过,我觉得关于这个话题继续说下去,这个帖子就成水贴了,失去他原有的价值了,我们还是停吧?
34 楼 Agrael 2010-05-22  
Norther 写道
Agrael 写道
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。


计算机就是洋人发明的,顺你这个思路下去,我们还应当别写程序,拒绝计算机,优先使用毛笔,宣纸和算盘。

我非常不认同把事情往民族主义上扯的做法。


我对写注释的态度居然变成民族主义。。。。。。
33 楼 Norther 2010-05-22  
Agrael 写道
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。


计算机就是洋人发明的,顺你这个思路下去,我们还应当别写程序,拒绝计算机,优先使用毛笔,宣纸和算盘。

我非常不认同把事情往民族主义上扯的做法。
32 楼 Norther 2010-05-22  
Agrael 写道
Feiing 写道
Agrael 写道
Feiing 写道
Agrael 写道
private static final transient Map<Class<?>, CacheBeanInfo> CACHE_BEANINFO = new ReferenceMap<Class<?>, CacheBeanInfo>(ReferenceKeyType.WEAK,ReferenceValueType.SOFT);

自己写的一个ReferenceMap,封装了ConcurrentHashMap。
其实有时候自己多留意一下多用心,很多东西并不是不可能。
在使用开源包的时候,还是要自己思考下如果是自己的话该如何实现。不然真成了只会找开源的人了。


没仔细看你的代码, 但请允许我凭臆断说几句大言不惭的话

1. 我不认为你的实现会比 google-collections 优秀, 因为 :
2. 我不认为你的水平会比 Bob Lee 或者 Doug Lea 高

所以

3. 我会在项目里用公认的优秀类库而不会因为自己开心就写一些帮助不大的东西

因为

4. 这会导致项目的维护成本增加

如果我想让别人认可我的作品

5. 如果允许, 我会把它开源让所有的人来试用, 我会写一个 feature list comparison 来比较它跟其他作品, 代码放在那, 孰优孰劣大家心里都会很明白

另外 , 个人认为用中文写注释是一个非常坏的习惯



我并没说和什么相比,我只是说自己多留意一下多用心,很多东西并不是不可能。
我也没和google-collections比,当然我的水平没有 Bob Lee 或者 Doug Lea 高,但是,请先看明白我想说的是什么:)


楼主的主题是 google-collections MapMaker,  你上来就贴一个自己的类似实现, 如果这不是比较, 请问你想说什么?



貌似你不仅没看我写的东西,你还没仔细看楼主的回复就说了这些话,我那个是楼主说是否可以看看,我才发的。
在这之前,我只是想说明 自己多留意一下多用心,很多东西并不是不可能。 仅此而已。


仅此而已,就是仅表达了你认为“我没留意,我不用心”。但我这么起劲研究大牛代码的人,怎么就被你描述成不用心呢?
31 楼 Agrael 2010-05-22  
Feiing 写道
Agrael 写道
Feiing 写道
Agrael 写道
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。


我不喜欢把技术跟国家民族联系起来, 也不认为中国人就应该用中文写注释, 当然如果你能写程序也用中文那就另当别论


那你认为中国人应该写什么文注释呢?
至于你的 当然如果你能写程序也用中文那就另当别论 这句话,我个人觉得带有强烈的攻击性。


当然是英文, 我不明白为什么程序是英文注释却要用中文, 也不觉得我说的话有什么攻击性


其实这个并不矛盾不是吗?你爱用英文有你的理由,我要用中文有我的理由。大家以后还是按照自己的做就是了,不是吗?毕竟没有规范写着必须要用什么语言写注释。我觉得这个话题可以就此结束了。你觉得呢?
30 楼 Agrael 2010-05-22  
Feiing 写道
Agrael 写道


貌似你不仅没看我写的东西,你还没仔细看楼主的回复就说了这些话,我那个是楼主说是否可以看看,我才发的。
在这之前,我只是想说明 自己多留意一下多用心,很多东西并不是不可能。 仅此而已。


貌似从来也没人说过 什么东西不可能 之类的话,

另外, 我虽然只是一目十行的看了你的代码,  但说句心里话, 不论是技巧还是建壮性相比 google-collections 你都相差甚远




什么东西不可能 和 自己多留意一下多用心,很多东西并不是不可能 貌似差别很大。

我一再强调,我并没和 google-collections 比的意思。
貌似拿它们去比的一直都是你?
就这个话题,我想我的观点已经很明确了。如果你还是要继续比,我也没办法。
29 楼 murainwood 2010-05-21  
Norther 写道
beneo 写道
不会是 Doug Lea 跑到 google 又去弄了一个 concurrent package 吧



是的,里面的部分实现确实是Doug Lea贡献的。

Doug Lea的牌子,够硬
28 楼 Feiing 2010-05-21  
Agrael 写道
Feiing 写道
Agrael 写道
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。


我不喜欢把技术跟国家民族联系起来, 也不认为中国人就应该用中文写注释, 当然如果你能写程序也用中文那就另当别论


那你认为中国人应该写什么文注释呢?
至于你的 当然如果你能写程序也用中文那就另当别论 这句话,我个人觉得带有强烈的攻击性。


当然是英文, 我不明白为什么程序是英文注释却要用中文, 也不觉得我说的话有什么攻击性
27 楼 Feiing 2010-05-21  
Agrael 写道


貌似你不仅没看我写的东西,你还没仔细看楼主的回复就说了这些话,我那个是楼主说是否可以看看,我才发的。
在这之前,我只是想说明 自己多留意一下多用心,很多东西并不是不可能。 仅此而已。


貌似从来也没人说过 什么东西不可能 之类的话,

另外, 我虽然只是一目十行的看了你的代码,  但说句心里话, 不论是技巧还是建壮性相比 google-collections 你都相差甚远


26 楼 Agrael 2010-05-21  
Feiing 写道
Agrael 写道
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。


我不喜欢把技术跟国家民族联系起来, 也不认为中国人就应该用中文写注释, 当然如果你能写程序也用中文那就另当别论


那你认为中国人应该写什么文注释呢?
至于你的 当然如果你能写程序也用中文那就另当别论 这句话,我个人觉得带有强烈的攻击性。
25 楼 Feiing 2010-05-21  
Agrael 写道
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。


我不喜欢把技术跟国家民族联系起来, 也不认为中国人就应该用中文写注释, 当然如果你能写程序也用中文那就另当别论
24 楼 Agrael 2010-05-21  
Feiing 写道
Agrael 写道
Feiing 写道
Agrael 写道
private static final transient Map<Class<?>, CacheBeanInfo> CACHE_BEANINFO = new ReferenceMap<Class<?>, CacheBeanInfo>(ReferenceKeyType.WEAK,ReferenceValueType.SOFT);

自己写的一个ReferenceMap,封装了ConcurrentHashMap。
其实有时候自己多留意一下多用心,很多东西并不是不可能。
在使用开源包的时候,还是要自己思考下如果是自己的话该如何实现。不然真成了只会找开源的人了。


没仔细看你的代码, 但请允许我凭臆断说几句大言不惭的话

1. 我不认为你的实现会比 google-collections 优秀, 因为 :
2. 我不认为你的水平会比 Bob Lee 或者 Doug Lea 高

所以

3. 我会在项目里用公认的优秀类库而不会因为自己开心就写一些帮助不大的东西

因为

4. 这会导致项目的维护成本增加

如果我想让别人认可我的作品

5. 如果允许, 我会把它开源让所有的人来试用, 我会写一个 feature list comparison 来比较它跟其他作品, 代码放在那, 孰优孰劣大家心里都会很明白

另外 , 个人认为用中文写注释是一个非常坏的习惯



我并没说和什么相比,我只是说自己多留意一下多用心,很多东西并不是不可能。
我也没和google-collections比,当然我的水平没有 Bob Lee 或者 Doug Lea 高,但是,请先看明白我想说的是什么:)


楼主的主题是 google-collections MapMaker,  你上来就贴一个自己的类似实现, 如果这不是比较, 请问你想说什么?



貌似你不仅没看我写的东西,你还没仔细看楼主的回复就说了这些话,我那个是楼主说是否可以看看,我才发的。
在这之前,我只是想说明 自己多留意一下多用心,很多东西并不是不可能。 仅此而已。
23 楼 Feiing 2010-05-21  
Agrael 写道
Feiing 写道
Agrael 写道
private static final transient Map<Class<?>, CacheBeanInfo> CACHE_BEANINFO = new ReferenceMap<Class<?>, CacheBeanInfo>(ReferenceKeyType.WEAK,ReferenceValueType.SOFT);

自己写的一个ReferenceMap,封装了ConcurrentHashMap。
其实有时候自己多留意一下多用心,很多东西并不是不可能。
在使用开源包的时候,还是要自己思考下如果是自己的话该如何实现。不然真成了只会找开源的人了。


没仔细看你的代码, 但请允许我凭臆断说几句大言不惭的话

1. 我不认为你的实现会比 google-collections 优秀, 因为 :
2. 我不认为你的水平会比 Bob Lee 或者 Doug Lea 高

所以

3. 我会在项目里用公认的优秀类库而不会因为自己开心就写一些帮助不大的东西

因为

4. 这会导致项目的维护成本增加

如果我想让别人认可我的作品

5. 如果允许, 我会把它开源让所有的人来试用, 我会写一个 feature list comparison 来比较它跟其他作品, 代码放在那, 孰优孰劣大家心里都会很明白

另外 , 个人认为用中文写注释是一个非常坏的习惯



我并没说和什么相比,我只是说自己多留意一下多用心,很多东西并不是不可能。
我也没和google-collections比,当然我的水平没有 Bob Lee 或者 Doug Lea 高,但是,请先看明白我想说的是什么:)


楼主的主题是 google-collections MapMaker,  你上来就贴一个自己的类似实现, 如果这不是比较, 请问你想说什么?
22 楼 Agrael 2010-05-21  
我觉得我是中国人,写注释理应用中文。如果真的有外国朋友需要而看不懂,我会再提供一份英文的。但是,无论何时,我都优先使用中文,就像我把我写的struts2-ejb3-plugin提交给apache一样使用中文。因为我是中国人。

相关推荐

    Google-Guava-Collections-使用介绍

    Google Guava Collections 是 Java Collections Framework 的一个强大且实用的非官方扩展 API。它由 Google 工程师 Kevin Bourrillion 和 Jared Levy 在著名的“20%”时间开发而成,并得到了 Java Collections ...

    Google_Guava_Collections_使用介绍.pdf )

    ### Google Guava Collections 使用介绍 #### 一、Google Guava Collections 概览 Google Guava Collections,简称Guava Collections,是对Java Collections Framework进行增强和扩展的开源项目。它由Google工程师...

    guava collection简介1

    Guava Collections 是 Google 的工程师 Kevin Bourrillion 和 Jared Levy 创作的一个开源库,利用他们在公司内部“20%”自由时间开发的成果。这个库是对 Java Collections Framework 的一个增强和扩展,旨在提供更...

    com.google.common.collect jar包

    是Google Guava库的一部分,Guava是Google的一个开源项目,旨在提供一系列现代Java实践,包括高效的数据结构、实用的并发工具、字符串处理以及I/O等。Guava库中的`collect`模块专注于提供更高级别的集合操作,例如...

    google common jar包

    在Android开发中,`google-collections-1.0.jar`(现在通常被称为`guava.jar`,版本可能已更新至29.x或更高)是一个非常重要的依赖。它可以帮助开发者编写更简洁、更安全的代码,提高代码的可读性和可维护性。尤其是...

Global site tag (gtag.js) - Google Analytics