成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JS 實(shí)現(xiàn)緩存算法(FIFO/LRU)

awokezhou / 2612人閱讀

摘要:最簡(jiǎn)單的一種緩存算法,設(shè)置緩存上限,當(dāng)達(dá)到了緩存上限的時(shí)候,按照先進(jìn)先出的策略進(jìn)行淘汰,再增加進(jìn)新的。隊(duì)列算法實(shí)現(xiàn)緩存需要一個(gè)對(duì)象和一個(gè)數(shù)組作為輔助數(shù)組記錄進(jìn)入順序先進(jìn)先出,刪除隊(duì)列第一個(gè)元素?zé)o論存在與否都對(duì)中的賦值,最近最少使用算法。

FIFO

最簡(jiǎn)單的一種緩存算法,設(shè)置緩存上限,當(dāng)達(dá)到了緩存上限的時(shí)候,按照先進(jìn)先出的策略進(jìn)行淘汰,再增加進(jìn)新的 k-v 。

使用了一個(gè)對(duì)象作為緩存,一個(gè)數(shù)組配合著記錄添加進(jìn)對(duì)象時(shí)的順序,判斷是否到達(dá)上限,若到達(dá)上限取數(shù)組中的第一個(gè)元素key,對(duì)應(yīng)刪除對(duì)象中的鍵值。

/**
 * FIFO隊(duì)列算法實(shí)現(xiàn)緩存
 * 需要一個(gè)對(duì)象和一個(gè)數(shù)組作為輔助
 * 數(shù)組記錄進(jìn)入順序
 */
class FifoCache{
    constructor(limit){
        this.limit = limit || 10
        this.map = {}
        this.keys = []
    }
    set(key,value){
        let map = this.map
        let keys = this.keys
        if (!Object.prototype.hasOwnProperty.call(map,key)) {
            if (keys.length === this.limit) {
                delete map[keys.shift()]//先進(jìn)先出,刪除隊(duì)列第一個(gè)元素
            }
            keys.push(key)
        }
        map[key] = value//無論存在與否都對(duì)map中的key賦值
    }
    get(key){
        return this.map[key]
    }
}

module.exports = FifoCache
LRU

LRU(Least recently used,最近最少使用)算法。該算法的觀點(diǎn)是,最近被訪問的數(shù)據(jù)那么它將來訪問的概率就大,緩存滿的時(shí)候,優(yōu)先淘汰最無人問津者

算法實(shí)現(xiàn)思路:基于一個(gè)雙鏈表的數(shù)據(jù)結(jié)構(gòu),在沒有滿員的情況下,新來的 k-v 放在鏈表的頭部,以后每次獲取緩存中的 k-v 時(shí)就將該k-v移到最前面,緩存滿的時(shí)候優(yōu)先淘汰末尾的。

雙向鏈表的特點(diǎn),具有頭尾指針,每個(gè)節(jié)點(diǎn)都有 prev(前驅(qū)) 和 next(后繼) 指針分別指向他的前一個(gè)和后一個(gè)節(jié)點(diǎn)。

關(guān)鍵點(diǎn):在雙鏈表的插入過程中要注意順序問題,一定是在保持鏈表不斷的情況下先處理指針,最后才將原頭指針指向新插入的元素,在代碼的實(shí)現(xiàn)中請(qǐng)注意看我在注釋中說明的順序注意點(diǎn)!

class LruCache {
    constructor(limit) {
        this.limit = limit || 10
        //head 指針指向表頭元素,即為最常用的元素
        this.head = this.tail = undefined
        this.map = {}
        this.size = 0
    }
    get(key, IfreturnNode) {
        let node = this.map[key]
        // 如果查找不到含有`key`這個(gè)屬性的緩存對(duì)象
        if (node === undefined) return
        // 如果查找到的緩存對(duì)象已經(jīng)是 tail (最近使用過的)
        if (node === this.head) { //判斷該節(jié)點(diǎn)是不是是第一個(gè)節(jié)點(diǎn)
            // 是的話,皆大歡喜,不用移動(dòng)元素,直接返回
            return returnnode ?
                node :
                node.value
        }
        // 不是頭結(jié)點(diǎn),鐵定要移動(dòng)元素了
        if (node.prev) { //首先要判斷該節(jié)點(diǎn)是不是有前驅(qū)
            if (node === this.tail) { //有前驅(qū),若是尾節(jié)點(diǎn)的話多一步,讓尾指針指向當(dāng)前節(jié)點(diǎn)的前驅(qū)
                this.tail = node.prev
            }
            //把當(dāng)前節(jié)點(diǎn)的后繼交接給當(dāng)前節(jié)點(diǎn)的前驅(qū)去指向。
            node.prev.next = node.next
        }
        if (node.next) { //判斷該節(jié)點(diǎn)是不是有后繼
            //有后繼的話直接讓后繼的前驅(qū)指向當(dāng)前節(jié)點(diǎn)的前驅(qū)
            node.next.prev = node.prev
            //整個(gè)一個(gè)過程就是把當(dāng)前節(jié)點(diǎn)拿出來,并且保證鏈表不斷,下面開始移動(dòng)當(dāng)前節(jié)點(diǎn)了
        }
        node.prev = undefined //移動(dòng)到最前面,所以沒了前驅(qū)
        node.next = this.head //注意?。?! 這里要先把之前的排頭給接到手?。。?!讓當(dāng)前節(jié)點(diǎn)的后繼指向原排頭
        if (this.head) {
            this.head.prev = node //讓之前的排頭的前驅(qū)指向現(xiàn)在的節(jié)點(diǎn)
        }
        this.head = node //完成了交接,才能執(zhí)行此步!不然就找不到之前的排頭啦!
        return IfreturnNode ?
            node :
            node.value
    }
    set(key, value) {
        // 之前的算法可以直接存k-v但是現(xiàn)在要把簡(jiǎn)單的 k-v 封裝成一個(gè)滿足雙鏈表的節(jié)點(diǎn)
        //1.查看是否已經(jīng)有了該節(jié)點(diǎn)
        let node = this.get(key, true)
        if (!node) {
            if (this.size === this.limit) { //判斷緩存是否達(dá)到上限
                //達(dá)到了,要?jiǎng)h最后一個(gè)節(jié)點(diǎn)了。
                if (this.tail) {
                    this.tail = this.tail.prev
                    this.tail.prev.next = undefined
                    //平滑斷鏈之后,銷毀當(dāng)前節(jié)點(diǎn)
                    this.tail.prev = this.tail.next = undefined
                    this.map[this.tail.key] = undefined
                    //當(dāng)前緩存內(nèi)存釋放一個(gè)槽位
                    this.size--
                }
                node = {
                    key: key
                }
                this.map[key] = node
                if(this.head){//判斷緩存里面是不是有節(jié)點(diǎn)
                    this.head.prev = node
                    node.next = this.head
                }else{
                    //緩存里沒有值,皆大歡喜,直接讓head指向新節(jié)點(diǎn)就行了
                    this.head = node
                    this.tail = node
                }
                this.size++//減少一個(gè)緩存槽位
            }
        }
        //節(jié)點(diǎn)存不存在都要給他重新賦值啊
        node.value = value
    }
}

module.exports = LruCache

具體的思路就是如果所要get的節(jié)點(diǎn)不是頭結(jié)點(diǎn)(即已經(jīng)是最近使用的節(jié)點(diǎn)了,不需要移動(dòng)節(jié)點(diǎn)位置)要先進(jìn)行平滑的斷鏈操作,處理好指針指向的關(guān)系,拿出需要移動(dòng)到最前面的節(jié)點(diǎn),進(jìn)行鏈表的插入操作。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93506.html

相關(guān)文章

  • 《CDN 之我見》系列二:原理篇(緩存、安全)

    摘要:真正要做高性能的系統(tǒng),不僅需要在數(shù)據(jù)結(jié)構(gòu)與算法層面深入,更要從硬件操作系統(tǒng)文件系統(tǒng)底層原理等多個(gè)領(lǐng)域做更多的研究例如阿里云自研的系統(tǒng)使用了裸盤技術(shù)。 《CDN之我見》共由三個(gè)篇章組成,分為原理篇、詳解篇和隕坑篇。本篇章適合那些從未接觸過、或僅了解一些 CDN 專業(yè)術(shù)語,想深入了解和感受 CDN 究竟是什么的同學(xué)。本次由白金老師繼續(xù)為大家分享《CDN之我見》系列二,主要講解緩存是什么、工...

    maxmin 評(píng)論0 收藏0
  • 《CDN 之我見》系列二:原理篇(緩存、安全)

    摘要:真正要做高性能的系統(tǒng),不僅需要在數(shù)據(jù)結(jié)構(gòu)與算法層面深入,更要從硬件操作系統(tǒng)文件系統(tǒng)底層原理等多個(gè)領(lǐng)域做更多的研究例如阿里云自研的系統(tǒng)使用了裸盤技術(shù)。 《CDN之我見》共由三個(gè)篇章組成,分為原理篇、詳解篇和隕坑篇。本篇章適合那些從未接觸過、或僅了解一些 CDN 專業(yè)術(shù)語,想深入了解和感受 CDN 究竟是什么的同學(xué)。本次由白金老師繼續(xù)為大家分享《CDN之我見》系列二,主要講解緩存是什么、工...

    rainyang 評(píng)論0 收藏0
  • 你應(yīng)該知道的緩存進(jìn)化史

    摘要:先簡(jiǎn)單介紹一下愛奇藝的緩存道路的發(fā)展吧??梢钥匆妶D中分為幾個(gè)階段第一階段數(shù)據(jù)同步加通過消息隊(duì)列進(jìn)行數(shù)據(jù)同步至,然后應(yīng)用直接去取緩存這個(gè)階段優(yōu)點(diǎn)是由于是使用的分布式緩存,所以數(shù)據(jù)更新快。愛奇藝的緩存的發(fā)展也是基于此之上,通過對(duì)的二次開發(fā) 1.背景 本文是上周去技術(shù)沙龍聽了一下愛奇藝的Java緩存之路有感寫出來的。先簡(jiǎn)單介紹一下愛奇藝的java緩存道路的發(fā)展吧。 showImg(https...

    remcarpediem 評(píng)論0 收藏0
  • 你應(yīng)該知道的緩存進(jìn)化史

    摘要:先簡(jiǎn)單介紹一下愛奇藝的緩存道路的發(fā)展吧??梢钥匆妶D中分為幾個(gè)階段第一階段數(shù)據(jù)同步加通過消息隊(duì)列進(jìn)行數(shù)據(jù)同步至,然后應(yīng)用直接去取緩存這個(gè)階段優(yōu)點(diǎn)是由于是使用的分布式緩存,所以數(shù)據(jù)更新快。愛奇藝的緩存的發(fā)展也是基于此之上,通過對(duì)的二次開發(fā) 1.背景 本文是上周去技術(shù)沙龍聽了一下愛奇藝的Java緩存之路有感寫出來的。先簡(jiǎn)單介紹一下愛奇藝的java緩存道路的發(fā)展吧。 showImg(https...

    Tangpj 評(píng)論0 收藏0
  • 【Mybatis系列】從源碼角度深度理解Mybatis的緩存特性

    摘要:一級(jí)緩存介紹及相關(guān)配置。在這個(gè)章節(jié),我們學(xué)習(xí)如何使用的一級(jí)緩存。一級(jí)緩存實(shí)驗(yàn)配置完畢后,通過實(shí)驗(yàn)的方式了解一級(jí)緩存的效果。源碼分析了解具體的工作流程后,我們隊(duì)查詢相關(guān)的核心類和一級(jí)緩存的源碼進(jìn)行走讀。 我,后端Java工程師,現(xiàn)在美團(tuán)點(diǎn)評(píng)工作。愛健身,愛技術(shù),也喜歡寫點(diǎn)文字。個(gè)人網(wǎng)站: http://kailuncen.me公眾號(hào): KailunTalk (凱倫說) 前言 本文主要涉及...

    Ku_Andrew 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<