av手机免费在线观看,国产女人在线视频,国产xxxx免费,捆绑调教一二三区,97影院最新理论片,色之久久综合,国产精品日韩欧美一区二区三区

java語(yǔ)言

Java如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存

時(shí)間:2025-04-13 20:10:32 java語(yǔ)言 我要投稿
  • 相關(guān)推薦

Java如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存

  緩存是在web開(kāi)發(fā)中經(jīng)常用到的,將程序經(jīng)常使用到或調(diào)用到的對(duì)象存在內(nèi)存中,或者是耗時(shí)較長(zhǎng)但又不具有實(shí)時(shí)性的查詢(xún)數(shù)據(jù)放入內(nèi)存中,在一定程度上可以提高性能和效率。那么,用Java如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存?下面百分網(wǎng)小編帶大家一起來(lái)看看詳細(xì)內(nèi)容,希望對(duì)大家有所幫助!想了解更多相關(guān)信息請(qǐng)持續(xù)關(guān)注我們應(yīng)屆畢業(yè)生考試網(wǎng)!

  創(chuàng)建緩存對(duì)象EntityCache.java

  public class EntityCache {

  /**

  * 保存的數(shù)據(jù)

  */

  private Object datas;

  /**

  * 設(shè)置數(shù)據(jù)失效時(shí)間,為0表示永不失效

  */

  private long timeOut;

  /**

  * 最后刷新時(shí)間

  */

  private long lastRefeshTime;

  public EntityCache(Object datas, long timeOut, long lastRefeshTime) {

  this.datas = datas;

  this.timeOut = timeOut;

  this.lastRefeshTime = lastRefeshTime;

  }

  public Object getDatas() {

  return datas;

  }

  public void setDatas(Object datas) {

  this.datas = datas;

  }

  public long getTimeOut() {

  return timeOut;

  }

  public void setTimeOut(long timeOut) {

  this.timeOut = timeOut;

  }

  public long getLastRefeshTime() {

  return lastRefeshTime;

  }

  public void setLastRefeshTime(long lastRefeshTime) {

  this.lastRefeshTime = lastRefeshTime;

  }

  }

  定義緩存操作接口,ICacheManager.java

  public interface ICacheManager {

  /**

  * 存入緩存

  * @param key

  * @param cache

  */

  void putCache(String key, EntityCache cache);

  /**

  * 存入緩存

  * @param key

  * @param cache

  */

  void putCache(String key, Object datas, long timeOut);

  /**

  * 獲取對(duì)應(yīng)緩存

  * @param key

  * @return

  */

  EntityCache getCacheByKey(String key);

  /**

  * 獲取對(duì)應(yīng)緩存

  * @param key

  * @return

  */

  Object getCacheDataByKey(String key);

  /**

  * 獲取所有緩存

  * @param key

  * @return

  */

  Map<String, EntityCache> getCacheAll();

  /**

  * 判斷是否在緩存中

  * @param key

  * @return

  */

  boolean isContains(String key);

  /**

  * 清除所有緩存

  */

  void clearAll();

  /**

  * 清除對(duì)應(yīng)緩存

  * @param key

  */

  void clearByKey(String key);

  /**

  * 緩存是否超時(shí)失效

  * @param key

  * @return

  */

  boolean isTimeOut(String key);

  /**

  * 獲取所有key

  * @return

  */

  Set<String> getAllKeys();

  }

  實(shí)現(xiàn)接口ICacheManager,CacheManagerImpl.java

  這里我使用了ConcurrentHashMap來(lái)保存緩存,本來(lái)以為這樣就是線程安全的,其實(shí)不然,在后面的測(cè)試中會(huì)發(fā)現(xiàn)它并不是線程安全的。

  public class CacheManagerImpl implements ICacheManager {

  private static Map<String, EntityCache> caches = new ConcurrentHashMap<String, EntityCache>();

  /**

  * 存入緩存

  * @param key

  * @param cache

  */

  public void putCache(String key, EntityCache cache) {

  caches.put(key, cache);

  }

  /**

  * 存入緩存

  * @param key

  * @param cache

  */

  public void putCache(String key, Object datas, long timeOut) {

  timeOut = timeOut > 0 ? timeOut : 0L;

  putCache(key, new EntityCache(datas, timeOut, System.currentTimeMillis()));

  }

  /**

  * 獲取對(duì)應(yīng)緩存

  * @param key

  * @return

  */

  public EntityCache getCacheByKey(String key) {

  if (this.isContains(key)) {

  return caches.get(key);

  }

  return null;

  }

  /**

  * 獲取對(duì)應(yīng)緩存

  * @param key

  * @return

  */

  public Object getCacheDataByKey(String key) {

  if (this.isContains(key)) {

  return caches.get(key).getDatas();

  }

  return null;

  }

  /**

  * 獲取所有緩存

  * @param key

  * @return

  */

  public Map<String, EntityCache> getCacheAll() {

  return caches;

  }

  /**

  * 判斷是否在緩存中

  * @param key

  * @return

  */

  public boolean isContains(String key) {

  return caches.containsKey(key);

  }

  /**

  * 清除所有緩存

  */

  public void clearAll() {

  caches.clear();

  }

  /**

  * 清除對(duì)應(yīng)緩存

  * @param key

  */

  public void clearByKey(String key) {

  if (this.isContains(key)) {

  caches.remove(key);

  }

  }

  /**

  * 緩存是否超時(shí)失效

  * @param key

  * @return

  */

  public boolean isTimeOut(String key) {

  if (!caches.containsKey(key)) {

  return true;

  }

  EntityCache cache = caches.get(key);

  long timeOut = cache.getTimeOut();

  long lastRefreshTime = cache.getLastRefeshTime();

  if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime >= timeOut) {

  return true;

  }

  return false;

  }

  /**

  * 獲取所有key

  * @return

  */

  public Set<String> getAllKeys() {

  return caches.keySet();

  }

  }

  CacheListener.java,監(jiān)聽(tīng)失效數(shù)據(jù)并移除。

  public class CacheListener{

  Logger logger = Logger.getLogger("cacheLog");

  private CacheManagerImpl cacheManagerImpl;

  public CacheListener(CacheManagerImpl cacheManagerImpl) {

  this.cacheManagerImpl = cacheManagerImpl;

  }

  public void startListen() {

  new Thread(){

  public void run() {

  while (true) {

  for(String key : cacheManagerImpl.getAllKeys()) {

  if (cacheManagerImpl.isTimeOut(key)) {

  cacheManagerImpl.clearByKey(key);

  logger.info(key + "緩存被清除");

  }

  }

  }

  }

  }.start();

  }

  }

  測(cè)試類(lèi)TestCache.java

  public class TestCache {

  Logger logger = Logger.getLogger("cacheLog");

  /**

  * 測(cè)試緩存和緩存失效

  */

  @Test

  public void testCacheManager() {

  CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();

  cacheManagerImpl.putCache("test", "test", 10 * 1000L);

  cacheManagerImpl.putCache("myTest", "myTest", 15 * 1000L);

  CacheListener cacheListener = new CacheListener(cacheManagerImpl);

  cacheListener.startListen();

  logger.info("test:" + cacheManagerImpl.getCacheByKey("test").getDatas());

  logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest").getDatas());

  try {

  TimeUnit.SECONDS.sleep(20);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  logger.info("test:" + cacheManagerImpl.getCacheByKey("test"));

  logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest"));

  }

  /**

  * 測(cè)試線程安全

  */

  @Test

  public void testThredSafe() {

  final String key = "thread";

  final CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();

  ExecutorService exec = Executors.newCachedThreadPool();

  for (int i = 0; i < 100; i++) {

  exec.execute(new Runnable() {

  public void run() {

  if (!cacheManagerImpl.isContains(key)) {

  cacheManagerImpl.putCache(key, 1, 0);

  } else {

  //因?yàn)?1和賦值操作不是原子性的,所以把它用synchronize塊包起來(lái)

  synchronized (cacheManagerImpl) {

  int value = (Integer) cacheManagerImpl.getCacheDataByKey(key) + 1;

  cacheManagerImpl.putCache(key,value , 0);

  }

  }

  }

  });

  }

  exec.shutdown();

  try {

  exec.awaitTermination(1, TimeUnit.DAYS);

  } catch (InterruptedException e1) {

  e1.printStackTrace();

  }

  logger.info(cacheManagerImpl.getCacheDataByKey(key).toString());

  }

  }

  testCacheManager()輸出結(jié)果如下:

  2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager

  信息: test:test

  2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager

  信息: myTest:myTest

  2017-4-17 10:34:01 io.github.brightloong.cache.CacheListener$1 run

  信息: test緩存被清除

  2017-4-17 10:34:06 io.github.brightloong.cache.CacheListener$1 run

  信息: myTest緩存被清除

  2017-4-17 10:34:11 io.github.brightloong.cache.TestCache testCacheManager

  信息: test:null

  2017-4-17 10:34:11 io.github.brightloong.cache.TestCache testCacheManager

  信息: myTest:null

  testThredSafe()輸出結(jié)果如下(選出了各種結(jié)果中的一個(gè)舉例):

  2017-4-17 10:35:36 io.github.brightloong.cache.TestCache testThredSafe

  信息: 96

  可以看到并不是預(yù)期的結(jié)果100,為什么呢?ConcurrentHashMap只能保證單次操作的原子性,但是當(dāng)復(fù)合使用的時(shí)候,沒(méi)辦法保證復(fù)合操作的原子性,以下代碼:

  if (!cacheManagerImpl.isContains(key)) {

  cacheManagerImpl.putCache(key, 1, 0);

  }

  多線程的時(shí)候回重復(fù)更新value,設(shè)置為1,所以出現(xiàn)結(jié)果不是預(yù)期的100。所以辦法就是在CacheManagerImpl.java中都加上synchronized,但是這樣一來(lái)相當(dāng)于操作都是串行,使用ConcurrentHashMap也沒(méi)有什么意義,不過(guò)只是簡(jiǎn)單的緩存還是可以的。或者對(duì)測(cè)試方法中的run里面加上synchronized塊也行,都是大同小異。更高效的方法我暫時(shí)也想不出來(lái),希望大家能多多指教。

【Java如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存】相關(guān)文章:

Java 中常用緩存Cache機(jī)制的實(shí)現(xiàn)08-27

java的緩存機(jī)制07-29

java的緩存機(jī)制簡(jiǎn)介09-06

php頁(yè)面緩存實(shí)現(xiàn)方法07-20

java如何實(shí)現(xiàn)漢諾塔08-08

Java 隊(duì)列實(shí)現(xiàn)原理及簡(jiǎn)單實(shí)現(xiàn)代碼09-13

java通用組合算法如何實(shí)現(xiàn)09-12

Java中如何實(shí)現(xiàn)顯示動(dòng)態(tài)的時(shí)間09-28

如何在java中實(shí)現(xiàn)左右鍵菜單10-30