缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。
创建缓存对象EntityCache.java
1 | public class EntityCache { |
定义缓存操作接口,ICacheManager.java
1 | public interface ICacheManager { |
实现接口ICacheManager,CacheManagerImpl.java
这里我使用了ConcurrentHashMap来保存缓存,本来以为这样就是线程安全的,其实不然,在后面的测试中会发现它并不是线程安全的。
1 | public class CacheManagerImpl implements ICacheManager { |
CacheListener.java,监听失效数据并移除。
1 | public class CacheListener{ |
测试类TestCache.java
1 | public class TestCache { |
testCacheManager()输出结果如下:
1 | 2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager |
testThredSafe()输出结果如下(选出了各种结果中的一个举例):
1 | 2017-4-17 10:35:36 io.github.brightloong.cache.TestCache testThredSafe |
可以看到并不是预期的结果100,为什么呢?ConcurrentHashMap只能保证单次操作的原子性,但是当复合使用的时候,没办法保证复合操作的原子性,以下代码:
1 | if (!cacheManagerImpl.isContains(key)) { |
多线程的时候回重复更新value,设置为1,所以出现结果不是预期的100。所以办法就是在CacheManagerImpl.java中都加上synchronized,但是这样一来相当于操作都是串行,使用ConcurrentHashMap也没有什么意义,不过只是简单的缓存还是可以的。或者对测试方法中的run里面加上synchronized块也行,都是大同小异。更高效的方法我暂时也想不出来,希望大家能多多指教。