成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

帶有過(guò)期時(shí)間的LRU實(shí)現(xiàn)(Java版)

開發(fā) 后端
LRU全稱是Least Recently Used,即最近最久未使用的意思。也就是說(shuō):如果一個(gè)數(shù)據(jù)在最近一段時(shí)間沒有被使用,將來(lái)被使用的機(jī)會(huì)也比較小。

 [[335620]]

在很早之前學(xué)操作系統(tǒng)的時(shí)候見過(guò)這個(gè)算法,后來(lái)見到的越來(lái)越多,以至于刷面經(jīng)的時(shí)候也看到了,總結(jié)一下:

一、什么是LRU

LRU全稱是Least Recently Used,即最近最久未使用的意思。也就是說(shuō):如果一個(gè)數(shù)據(jù)在最近一段時(shí)間沒有被使用,將來(lái)被使用的機(jī)會(huì)也比較小。

通常的使用場(chǎng)景就是緩存,比如說(shuō)操作系統(tǒng)中的頁(yè)面置換算法。實(shí)現(xiàn)的方案有很多,我看了很多博客,大多是給了四五種。這里為了簡(jiǎn)潔,只給出一種,是帶有過(guò)期時(shí)間的。其他的實(shí)現(xiàn)類似,就交給聰明的你吧!!

解決方案:利用鏈表加HashMap

每次來(lái)一個(gè)新數(shù)據(jù),首先判斷map中是否含有,有的話就移動(dòng)到隊(duì)頭,沒有的話就新建一個(gè)節(jié)點(diǎn),然后放進(jìn)來(lái)就好,對(duì)于帶過(guò)期時(shí)間的功能,只需要為每一個(gè)節(jié)點(diǎn)放一個(gè)過(guò)期時(shí)間,只要到了這個(gè)時(shí)間就直接刪除即可。

 

還有一個(gè)問題:多線程環(huán)境下應(yīng)該加鎖,為了保證鎖的靈活性,我們使用ConcurrentHashMap。

OK,下面我們就開始實(shí)現(xiàn):

二、代碼實(shí)現(xiàn)

1、定義節(jié)點(diǎn)

  1. //這個(gè)Node對(duì)用HashMap中每一個(gè)節(jié)點(diǎn) 
  2. class Node implements Comparable<Node> { 
  3.     private String key
  4.     private Object value; 
  5.     private long expireTime;//注意這個(gè)過(guò)期時(shí)間是一個(gè)時(shí)間點(diǎn),如11點(diǎn)11分 
  6.     public Node(String key, Object value, long expireTime) { 
  7.         this.value = value; 
  8.         this.key = key
  9.         this.expireTime = expireTime; 
  10.     } 
  11.     //按照過(guò)期時(shí)間進(jìn)行排序 
  12.     @Override 
  13.     public int compareTo(Node o) { 
  14.         long r = this.expireTime - o.expireTime; 
  15.         if (r > 0)  return 1; 
  16.         if (r < 0) return -1; 
  17.         return 0; 
  18.     } 

2、LRU實(shí)現(xiàn)

  1. public class LRU { 
  2.     // 變量1:用于設(shè)置清除過(guò)期數(shù)據(jù)的線程池 
  3.     private static ScheduledExecutorService swapExpiredPool  
  4.                   = new ScheduledThreadPoolExecutor(10); 
  5.     // 變量2:用戶存儲(chǔ)數(shù)據(jù),為了保證線程安全,使用了ConcurrentHashMap 
  6.     private ConcurrentHashMap<String, Node> cache = new ConcurrentHashMap<>(1024); 
  7.     // 變量3:保存最新的過(guò)期數(shù)據(jù),過(guò)期時(shí)間最小的數(shù)據(jù)排在隊(duì)列前 
  8.     private PriorityQueue<Node> expireQueue = new PriorityQueue<>(1024); 
  9.     // 構(gòu)造方法:只要有緩存了,過(guò)期清除線程就開始工作 
  10.     public LRU() { 
  11.         swapExpiredPool.scheduleWithFixedDelay(new ExpiredNode(), 3,3,TimeUnit.SECONDS); 
  12.     } 
  13.     //還有代碼。。。。。。。 

現(xiàn)在我們定義了幾個(gè)變量,然后還有一個(gè)構(gòu)造方法,意思是只要啟動(dòng)了這個(gè)LRU,就開始清除。清除的線程是ExpiredNode。我們來(lái)看一下:

3、過(guò)期清除線程方法

這個(gè)方法也就是ExpiredNode,當(dāng)做一個(gè)內(nèi)部類在LRU中。

  1. public class ExpiredNode implements Runnable { 
  2.         @Override 
  3.         public void run() { 
  4.             // 第一步:獲取當(dāng)前的時(shí)間 
  5.             long now = System.currentTimeMillis(); 
  6.             while (true) { 
  7.                 // 第二步:從過(guò)期隊(duì)列彈出隊(duì)首元素,如果不存在,或者不過(guò)期就返回 
  8.                 Node node = expireQueue.peek(); 
  9.                 if (node == null || node.expireTime > now)return
  10.                 // 第三步:過(guò)期了那就從緩存中刪除,并且還要從隊(duì)列彈出 
  11.                 cache.remove(node.key); 
  12.                 expireQueue.poll(); 
  13.             }// 此過(guò)程為while(true),一直進(jìn)行判斷和刪除操作 
  14.         } 
  15.     } 

現(xiàn)在知道了過(guò)期清除方法,下面看看如何添加數(shù)據(jù)。

4、set方法

  1. public Object set(String key, Object value, long ttl) { 
  2.         // 第一步:獲取過(guò)期時(shí)間點(diǎn) 
  3.         long expireTime = System.currentTimeMillis() + ttl; 
  4.         // 第二步:新建一個(gè)節(jié)點(diǎn) 
  5.         Node newNode = new Node(key, value, expireTime); 
  6.         // 第三步:cache中有的話就覆蓋,沒有就添加新的,過(guò)期時(shí)間隊(duì)列也要添加 
  7.         Node old = cache.put(key, newNode); 
  8.         expireQueue.add(newNode); 
  9.         // 第四步:如果該key存在數(shù)據(jù),還要從過(guò)期時(shí)間隊(duì)列刪除 
  10.         if (old != null) { 
  11.             expireQueue.remove(old); 
  12.             return old.value; 
  13.         } 
  14.         return null
  15.     } 

5、get方法

這個(gè)方法就比較簡(jiǎn)單了,直接獲取即可。

  1. public Object get(String key) { 
  2.     //第一步:從cache直接獲取,注意這個(gè)cache是一個(gè)HashMap 
  3.     Node n = cache.get(key); 
  4.     //第二步:如果n為空那就返回為null,不為空就返回相應(yīng)的值 
  5.     return n == null ? null : n.value; 

注意以上345的代碼都存放在LRU中。

過(guò)期時(shí)間的我們已經(jīng)知道了,其實(shí)就是添加了一個(gè)過(guò)期時(shí)間隊(duì)列,和一個(gè)過(guò)期清除的線程,清除的時(shí)候使用while(true)每次判斷隊(duì)列隊(duì)首是否過(guò)期,然后判斷是否返回和清除。設(shè)置方法的時(shí)候還要把新的node添加到queue,把舊的移除掉。而且我們使用了ConcurrentHashMap保證了線程安全。

本文轉(zhuǎn)載自微信公眾號(hào)「 愚公要移山」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 愚公要移山公眾號(hào)。

OK,今天的代碼就先寫到這。

 

責(zé)任編輯:武曉燕 來(lái)源: 愚公要移山
相關(guān)推薦

2021-02-22 09:23:55

LRU時(shí)間HashMap

2021-07-26 21:15:10

LRU緩存MongoDB

2015-07-29 10:31:16

Java緩存算法

2020-10-30 11:30:15

Least Recen

2022-06-17 07:49:14

緩存LRU

2015-07-15 10:19:16

Java代碼使用緩存

2023-07-06 12:39:14

RedisLRULFU

2020-02-19 19:18:02

緩存查詢速度淘汰算法

2009-07-23 11:11:18

LRU緩存

2020-12-17 12:31:16

javascriptDAOlocalStorag

2020-05-15 17:05:51

Oracle數(shù)據(jù)庫(kù)LRU算法

2019-12-24 10:32:01

OracleLRU臟塊

2024-05-08 10:03:50

2020-09-18 10:31:47

LRU算法數(shù)組

2024-04-09 08:39:16

本地緩存開發(fā)線程安全

2021-09-28 06:57:22

JWT過(guò)期生效

2021-03-01 18:42:02

緩存LRU算法

2021-06-21 15:49:39

React動(dòng)效組件

2011-12-16 10:45:12

java

2019-09-27 09:13:55

Redis內(nèi)存機(jī)制
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 中文字幕在线一 | 免费在线观看av | 国产一区高清 | 丁香久久| 国产精品视频一二三 | 天天操天天射天天舔 | 911影院| 九九在线精品视频 | 亚洲福利在线视频 | 亚洲欧美日韩电影 | 国产精品视频网 | 国产精品久久久亚洲 | 精品国产一区二区三区性色av | 日韩中文字幕网 | 日韩在线播放第一页 | 久久久99精品免费观看 | 亚洲看片 | 一区二区三区视频播放 | 夜夜精品浪潮av一区二区三区 | 久久国内 | 中文字幕第一页在线 | 国产亚洲精品精品国产亚洲综合 | 成人三级影院 | 欧洲免费毛片 | 精品视频在线播放 | 成人三级视频 | 超碰成人免费观看 | 亚洲永久入口 | 999国产精品视频 | 免费成人高清在线视频 | 热久久久 | 成人依人 | 日韩一级| 精品福利一区二区三区 | 国产精品一区二区视频 | 中文在线a在线 | 亚洲精品中文在线 | www国产成人免费观看视频,深夜成人网 | 荷兰欧美一级毛片 | 日韩欧美1区2区 | 欧美日韩中文字幕在线播放 |