记忆化,是一种为了提高应用程序性能的FP技术。程序加速是通过缓存函数的结果实现的,避免了重复计算带来的额外开销。
1、现在我们使用Dictionary作为缓存结构
打印结果:
可以看出第三次打印的结果跟第一次打印的结果相同,也就是被缓存在Dictionary中的值。
在单线程中我们这样写没有问题,程序顺序被执行,Dictionary不存在并发问题,但是当我们想在多个线程并行时Dictionary不是线程安全集合,会存在线程安全问题。
2、现在我们使用线程安全集合ConcurrentDictionary进行改进:(方法中注释已经对方法做了说明,在此不重复)
打印结果:
注解中我们说明了ConcurrentDictionary是线程安全集合,但是当我们使用GetOrAdd时,由于该方法不是原子性的操作,当进行初始化时,可能多个线程同时进行初始化操作,带来了额外的开销。
3、为解决GetOrAdd非原子性操作重复初始化操作,引入延迟初始化(注解已详细说明):
在看改进方法前我们先看下Lazy类的用法:
输出:
以下为Lazy类代码片段,从代码我们看出在对象未使用(value)前,实例并未真正创建:
现在我们看下改进方法:
到现在方法的线程安全、初始化加载问题都解决了,但是我们在解决重复计算的问题后却又不得不考虑缓存带来的内存损耗问题。我们实例化了ConcurrentDictionary对象,并且该对象作为强引用类型一直未被释放,那么GC是无法回收该对象,带来的问题是内存一直被占用,随着方法引用次数越来越多内存开销则会越来越大。
4、为解决该问题,我们引入过期时间,根据过期时间释放缓存值。
其他实现方式,使用WeakReference弱引用类型(以下为使用示例):
打印结果:
具体实现方式不在此实现。
Original: https://www.cnblogs.com/xtt321/p/14220813.html
Author: 温暖如太阳
Title: 函数式编程-记忆化缓存
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/593287/
转载文章受原作者版权保护。转载请注明原作者出处!