背景
工业界有很多成熟的系统,大多数都是分布式的缓存系统,如redis
,memcache
,Ehcache
等,它们被广泛运用于互联网公司中。缓存系统的一个重要应用就是减小数据库的压力,也可以缓存jsp,静态HTML,图片等资源。
这次说的缓存,并不是大型的分布式缓存系统,也没有类似LRU等过期机制,它仅仅是一个十分简单的HashMap
对象。但是,它主要是用来解决高并发下,对象仅仅被创建一次,并且创建对象的过程是个耗时操作。在高并发的情况下,多个线程可能需要同样一个数据,如果它们同时发现这个数据在内存中没有,那么,它们就都会去经过计算,如果这个计算是一个很耗时,那么就会很大程度的浪费系统的CPU资源。当然,concurrentHashMap
可以最终保证数据的唯一性,但是却没办法解决计算的唯一性。
因此,对于一个进程内,高并发下执行耗时操作创建同一个对象,对象仅被创建一次。我们使用FutureTask
+concurrentHashMap
来实现目标功能
代码示例
计算接口
|
|
接收一个A类型的参数,经过计算,输出V类型的数据。
计算任务
|
|
实现了Computable
接口,实现了计算过程,模拟一个相对耗时的操作
缓存Map(CacheMap)
|
|
CacheMap
是缓存数据的结构体,目标是以A类型为key,V类型为value的HashMap
。里面封装了一个concurrentHashMap
,以A类型为key,以FutureTask<V>
为value。
当在Map里没找到时,表示结果对象还没创建,也可能是另一个线程正在创建。新建一个Callable
的任务,并用FutureTask包起来
尝试将FutureTask<V>
放到Map
中,如果成功,返回null。由于concurrentHashMap
是线程安全的,只有一个能够放进去,其它则会阻塞等待。ret.run()
则会创建新的线程去执行计算,其它的会到ret.get()
阻塞等待结果。