古人云 (无图无真相, 有美女走光图为证):
引用
Pat-a-map, Pat-a-map, maker's man,
Make me a map as fast as you can...
这集要讲的工具叫
MapMaker.
顾名思义, MapMaker就是帮你作Map滴, 并且是as fast as it can! 实在是居家旅行, 制做Map的必备工具啊!
但是啊, 这计算机一思考, 你就笑了: "小样儿, 作Map还用你作啊? 当我文盲?" 不就是:
new HashMap<姓名, 奖金>()
嘛. 若是用上回书提到的Maps就是:
Maps.newHashMap();
再不, 用ImmutableMap, 就是
ImmutableMap.of("ajoo", 10000000000000000);
计算机: 这个, 这个, 啊, (耳语: 老大, 别这么不给面子啊. 出来混都不容易), 咱们这里讲的不是HashMap, 也不是ImmutableMap, 实际上是表明着当代最最高科技的
java.util.concurrent.ConcurrentMap
, 它适合多线程操做, 高并发, 无阻塞, 无死锁, 无冲突, 无测漏, 无...
你: 等等, 你是在说:
new ConcurrentHashMap<姓名, 奖金>()
这么简单到离谱的东西么?
计算机: 这个, 别急, 别急. 其实不彻底是. MapMaker提供了更多更强大的功能. 好比能够指定键是否用弱引用, 指定一个键多长时间过时之类的. 可是最最最有用的, 是那个
makeComputingMap()函数.
画面一转, ajoo平易近人地微笑着说: 对啦! 这也就是我今天要讲MapMaker的主要缘由.
你们想想, 平时有没有须要作延迟初始化(所谓lazy initialization)和缓存的? 好比说, 我要对每个须要用到的员工名字经过数据库查询她一年以来的加班多少, 加班是否自觉自愿, 漂亮程度, 身材和三围指标, 领会领导意图能力, 帮领导挡酒总加仑数等等等等各类数据, 最后通过一个NP问题的近似解决算法来获得员工的奖金数额.
这个东西算起来太费资源, 弄很差比奖金自己还多. 那么, 就要延迟计算, 只有员工主动跑来跟我要加薪, 我才去算. 并且要缓存, 若是这个员工对只发50元奖金心存不满, 反复来吵闹, 甚至投诉, 咱们不用从新计算.
通常若是你本身写怎么写呢? 假设我那个算奖金的函数写好了, 就叫computeBonus(姓名). 这样么?
class BonusManager {
private final Map<姓名, 奖金> cache = new HashMap<姓名, 奖金>();
奖金 getBonus(姓名 name) {
奖金 bonus = cache.get(name);
if (bonus == null) {
bonus = computeBonus(name); // 危险在这里!
}
cache.put(name, bonus);
return bonus;
}
}
其实主要逻辑是这样的. 问题是这个实现不是多线程安全的.
你能够在getBonus()上面加一个synchronized关键字, 而后它就线程安全了. 可是, 让咱们假设咱们是个跨国知名连锁大托拉斯, 须要极高极高的并发能力.
聪明如你必定会想到把HashMap改为ConcurrentHashMap.
近了一步了, 可是还不彻底. 这是由于两个线程可能同时执行if (bonus == null)而后同时去运行computeBonus(). 结果是, 咱们可能对某些名字重复运行computeBonus(). 让咱们再假设老板遇到这种你给公司浪费了资源的状况会炒你鱿鱼的.
呵呵, 到这里, 若是你想到了双检查锁机制(所谓的
double-checked locking), 那算你狠, 遇到大家这种聪明到煞风景的听众我真是无话可说, 卷帘朝散, 请假还宫!
而若是你没想到, 那么, 恭喜你, 你答对啦! 奖河南双汇火腿肠一根(94年珍藏版).
我想说的, 实际上是, 俺也不知道怎么写最好. 因此呀, 最好是不写. 反正MapMaker都给咱写好了不是? 人生苦短, 当及时行乐啊, 同志! 有闲功夫多洗几块尿布好很差?
那么, 不卖关子了 (等不及已经看了javadoc文档的同志们都已经本身写出来了. 俺再摇头晃脑故做玄虚恐怕就要吃臭鸡蛋, 烂西红柿伺候咯). 请看. 当当当当 (贝多芬第九交响曲响起)!
ConcurrentMap<名字, 奖金> cache = new MapMaker()
// 若是一个计算一年有效 (嗯, 明年奖金减半!), 那么设一个过时时间
.expiration(365, TimeUnit.DAYS)
.makeComputingMap(new Function<名字, 奖金>() {
@Override public 奖金 apply(名字 name) {
return computeBonus(name);
}
});
就是这么简单. 等等, 我先摆个pose先, 样子屌不屌? 这里面惟一须要解释的就是这个Function. 你们都知道, java是一门罗唆的语言艺术, 讲究说学逗唱, 不是, 说错了, 讲究类, 方法, 表达式, 匿名类等等等等, 反正是怎么写累人怎么来. 这里的目的其实就是告诉makeComputingMap()怎样"compute". 这个function是个匿名类, 它的apply()函数封装了怎么计算这么一个概念. (哎呀, 手都打酸了) 而后, makeComputingMap()就接手过去, 它内部怎么搞的咱不关心, 反正我上面想要的功能它全实现了, 这就够了呗. 行了, 洗尿布去了. 未完待续