本篇內(nèi)容主要講解“Java帶有過期時間的LRU實(shí)現(xiàn)方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java帶有過期時間的LRU實(shí)現(xiàn)方法是什么”吧!
創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司一直秉承“誠信做人,踏實(shí)做事”的原則,不欺瞞客戶,是我們最起碼的底線! 以服務(wù)為基礎(chǔ),以質(zhì)量求生存,以技術(shù)求發(fā)展,成交一個客戶多一個朋友!專注中小微企業(yè)官網(wǎng)定制,網(wǎng)站制作、成都網(wǎng)站制作,塑造企業(yè)網(wǎng)絡(luò)形象打造互聯(lián)網(wǎng)企業(yè)效應(yīng)。
一、什么是LRU
LRU全稱是Least Recently Used,即最近最久未使用的意思。也就是說:如果一個數(shù)據(jù)在最近一段時間沒有被使用,將來被使用的機(jī)會也比較小。
通常的使用場景就是緩存,比如說操作系統(tǒng)中的頁面置換算法。實(shí)現(xiàn)的方案有很多,我看了很多博客,大多是給了四五種。這里為了簡潔,只給出一種,是帶有過期時間的。其他的實(shí)現(xiàn)類似,就交給聰明的你吧!!
解決方案:利用鏈表加HashMap
每次來一個新數(shù)據(jù),首先判斷map中是否含有,有的話就移動到隊頭,沒有的話就新建一個節(jié)點(diǎn),然后放進(jìn)來就好,對于帶過期時間的功能,只需要為每一個節(jié)點(diǎn)放一個過期時間,只要到了這個時間就直接刪除即可。
還有一個問題:多線程環(huán)境下應(yīng)該加鎖,為了保證鎖的靈活性,我們使用ConcurrentHashMap。
OK,下面我們就開始實(shí)現(xiàn):
二、代碼實(shí)現(xiàn)
1、定義節(jié)點(diǎn)
//這個Node對用HashMap中每一個節(jié)點(diǎn) class Node implements Comparable<Node> { private String key; private Object value; private long expireTime;//注意這個過期時間是一個時間點(diǎn),如11點(diǎn)11分 public Node(String key, Object value, long expireTime) { this.value = value; this.key = key; this.expireTime = expireTime; } //按照過期時間進(jìn)行排序 @Override public int compareTo(Node o) { long r = this.expireTime - o.expireTime; if (r > 0) return 1; if (r < 0) return -1; return 0; } }
2、LRU實(shí)現(xiàn)
public class LRU { // 變量1:用于設(shè)置清除過期數(shù)據(jù)的線程池 private static ScheduledExecutorService swapExpiredPool = new ScheduledThreadPoolExecutor(10); // 變量2:用戶存儲數(shù)據(jù),為了保證線程安全,使用了ConcurrentHashMap private ConcurrentHashMap<String, Node> cache = new ConcurrentHashMap<>(1024); // 變量3:保存最新的過期數(shù)據(jù),過期時間最小的數(shù)據(jù)排在隊列前 private PriorityQueue<Node> expireQueue = new PriorityQueue<>(1024); // 構(gòu)造方法:只要有緩存了,過期清除線程就開始工作 public LRU() { swapExpiredPool.scheduleWithFixedDelay(new ExpiredNode(), 3,3,TimeUnit.SECONDS); } //還有代碼。。。。。。。 }
現(xiàn)在我們定義了幾個變量,然后還有一個構(gòu)造方法,意思是只要啟動了這個LRU,就開始清除。清除的線程是ExpiredNode。我們來看一下:
3、過期清除線程方法
這個方法也就是ExpiredNode,當(dāng)做一個內(nèi)部類在LRU中。
public class ExpiredNode implements Runnable { @Override public void run() { // 第一步:獲取當(dāng)前的時間 long now = System.currentTimeMillis(); while (true) { // 第二步:從過期隊列彈出隊首元素,如果不存在,或者不過期就返回 Node node = expireQueue.peek(); if (node == null || node.expireTime > now)return; // 第三步:過期了那就從緩存中刪除,并且還要從隊列彈出 cache.remove(node.key); expireQueue.poll(); }// 此過程為while(true),一直進(jìn)行判斷和刪除操作 } }
現(xiàn)在知道了過期清除方法,下面看看如何添加數(shù)據(jù)。
4、set方法
public Object set(String key, Object value, long ttl) { // 第一步:獲取過期時間點(diǎn) long expireTime = System.currentTimeMillis() + ttl; // 第二步:新建一個節(jié)點(diǎn) Node newNode = new Node(key, value, expireTime); // 第三步:cache中有的話就覆蓋,沒有就添加新的,過期時間隊列也要添加 Node old = cache.put(key, newNode); expireQueue.add(newNode); // 第四步:如果該key存在數(shù)據(jù),還要從過期時間隊列刪除 if (old != null) { expireQueue.remove(old); return old.value; } return null; }
5、get方法
這個方法就比較簡單了,直接獲取即可。
public Object get(String key) { //第一步:從cache直接獲取,注意這個cache是一個HashMap Node n = cache.get(key); //第二步:如果n為空那就返回為null,不為空就返回相應(yīng)的值 return n == null ? null : n.value; }
注意以上345的代碼都存放在LRU中。
過期時間的我們已經(jīng)知道了,其實(shí)就是添加了一個過期時間隊列,和一個過期清除的線程,清除的時候使用while(true)每次判斷隊列隊首是否過期,然后判斷是否返回和清除。設(shè)置方法的時候還要把新的node添加到queue,把舊的移除掉。而且我們使用了ConcurrentHashMap保證了線程安全。
到此,相信大家對“Java帶有過期時間的LRU實(shí)現(xiàn)方法是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
當(dāng)前文章:Java帶有過期時間的LRU實(shí)現(xiàn)方法是什么
鏈接URL:http://chinadenli.net/article28/geoecp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、云服務(wù)器、、品牌網(wǎng)站制作、網(wǎng)站設(shè)計公司、面包屑導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)