国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

網(wǎng)站優(yōu)化 前端怎么做營銷模式100個經(jīng)典案例

網(wǎng)站優(yōu)化 前端怎么做,營銷模式100個經(jīng)典案例,西寧網(wǎng)絡(luò)公司網(wǎng)站建設(shè),貿(mào)易公司做網(wǎng)站有優(yōu)勢嗎Guava LocalCache源碼分析:LocalCache的get、put、expand 前言一、get二、put三、expand 前言 上篇文章,詳細描寫了Guava LocalCache怎樣如ConcurrentHashMap對緩存數(shù)據(jù)進行了分段存儲。本章主要針對LocalCache重要的幾個接口進行說明。 一、get CanIg…

Guava LocalCache源碼分析:LocalCache的get、put、expand

  • 前言
  • 一、get
  • 二、put
  • 三、expand

前言

上篇文章,詳細描寫了Guava LocalCache怎樣如ConcurrentHashMap對緩存數(shù)據(jù)進行了分段存儲。本章主要針對LocalCache重要的幾個接口進行說明。

一、get

    @CanIgnoreReturnValue@Override@CheckForNullpublic V get(@CheckForNull Object key) {if (key == null) {return null;}int hash = hash(key);return segmentFor(hash).get(key, hash);}@CanIgnoreReturnValueV get(K key, CacheLoader<? super K, V> loader) throws ExecutionException {int hash = hash(checkNotNull(key));return segmentFor(hash).get(key, hash, loader);}

如上代碼,LocalCache的get方法首先根據(jù)key計算出hash值,并根據(jù)hash值找到對應(yīng)的segment,再調(diào)用segment的get方法獲取最終結(jié)果。

以傳入loader參數(shù)的get方法為例,看一下segment如何獲取值的。

        @CanIgnoreReturnValueV get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {checkNotNull(key);checkNotNull(loader);try {if (count != 0) {//不要調(diào)用getLiveEntry,這將忽略正在加載的值//根據(jù)key和hash獲取值ReferenceEntry<K, V> e = getEntry(key, hash);if (e != null) {//獲取當前時間long now = map.ticker.read();//判斷該值是否過期V value = getLiveValue(e, now);//如果未過期if (value != null) {//記錄讀取時間recordRead(e, now);//累計命中+1,這里Guava似乎認為當多條線程在更新統(tǒng)計數(shù)據(jù)時,//而不是細粒度同步控制的情況下,LongAdder比AtomicLong更好用。statsCounter.recordHits(1);//檢查是否需要刷新,如果設(shè)置了刷新時長且過了刷新時長,則刷新,否則返回該值return scheduleRefresh(e, key, hash, value, now, loader);}//值已經(jīng)過期ValueReference<K, V> valueReference = e.getValueReference();//如果增在加載if (valueReference.isLoading()) {//等待并返回加載后的值return waitForLoadingValue(e, key, valueReference);}}}//segment中為空或者未獲取到值//加鎖,嘗試從加載中的值中獲取,若獲取不到則調(diào)用load方法。return lockedGetOrLoad(key, hash, loader);} catch (ExecutionException ee) {Throwable cause = ee.getCause();if (cause instanceof Error) {throw new ExecutionError((Error) cause);} else if (cause instanceof RuntimeException) {throw new UncheckedExecutionException(cause);}throw ee;} finally {//累計到一定讀取次數(shù)后,清理超時緩存postReadCleanup();}}

相關(guān)調(diào)用邏輯如圖所示:
LocalCache的get方法

二、put

    public V put(K key, V value) {checkNotNull(key);checkNotNull(value);int hash = hash(key);return segmentFor(hash).put(key, hash, value, false);}

同樣,LocalCache的put方法也是首先根據(jù)key計算出hash值,并根據(jù)hash值找到對應(yīng)的segment,再調(diào)用segment的put方法。

        V put(K key, int hash, V value, boolean onlyIfAbsent) {//直接加鎖lock();try {long now = map.ticker.read();//清理過期緩存preWriteCleanup(now);//數(shù)量+1int newCount = this.count + 1;if (newCount > this.threshold) {//擴容expand();//因為擴容后的segment內(nèi)的緩存數(shù)量可能會變化,所以重新計算newCount = this.count + 1;}//找到要插入的位置,并獲取該位置的頭節(jié)點AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;int index = hash & (table.length() - 1);ReferenceEntry<K, V> first = table.get(index);//尋找該key是否存在for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {K entryKey = e.getKey();if (e.getHash() == hash&& entryKey != null//判斷key是否相等&& map.keyEquivalence.equivalent(key, entryKey)) {//意味著map中存在該key//獲取對應(yīng)的值ValueReference<K, V> valueReference = e.getValueReference();V entryValue = valueReference.get();//如果值是空的if (entryValue == null) {++modCount;//判斷該值是否在等待刪除中if (valueReference.isActive()) {//將舊值移放入移除通知隊列中,主要是Guava Cache有移除回調(diào)機制,故不能直接移除,隊列方便用于回調(diào)通知。enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.COLLECTED);//加入緩存setValue(e, key, value, now);//因為一刪一增,所以,數(shù)量不變newCount = this.count; // count remains unchanged} else {//加入緩存setValue(e, key, value, now);//這里不知道為啥又算了一遍,可能是再setValue中存在某些機制導(dǎo)致count發(fā)生了變化?newCount = this.count + 1;}this.count = newCount; // write-volatile//移除舊值evictEntries(e);return null;} else if (onlyIfAbsent) {//onlyIfAbsent為true,如果存在于map中,僅更新訪問時間recordLockedRead(e, now);return entryValue;} else {//刪除現(xiàn)有緩存,計數(shù)保持不變++modCount;enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED);setValue(e, key, value, now);evictEntries(e);return entryValue;}}}//map中不存在,則插入++modCount;ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);setValue(newEntry, key, value, now);table.set(index, newEntry);newCount = this.count + 1;this.count = newCount; // write-volatileevictEntries(newEntry);return null;} finally {//解鎖unlock();//清除過期緩存postWriteCleanup();}}

可見,整個put過程是用了鎖保證執(zhí)行的線程安全。

三、expand

LocalCache的擴容也是對段進行的擴容,當段的大小超過閾值時,便會出發(fā)擴容(詳細見上面的put函數(shù)),段的閾值為段大小的3/4,而每次擴容段的大小會變?yōu)樵瓉淼?倍。

代碼如下:

        @GuardedBy("this")void expand() {AtomicReferenceArray<ReferenceEntry<K, V>> oldTable = table;int oldCapacity = oldTable.length();//如果容量超過最大容量,直接返回if (oldCapacity >= MAXIMUM_CAPACITY) {return;}int newCount = count;//新段的大小是舊段的兩倍AtomicReferenceArray<ReferenceEntry<K, V>> newTable = newEntryArray(oldCapacity << 1);//閾值為新段大小的3/4threshold = newTable.length() * 3 / 4;//因為段擴容,所以要重新計算哈希映射int newMask = newTable.length() - 1;for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) {//我們需要保證對舊map的任何現(xiàn)有讀取都可以繼續(xù)進行。所以我們還不能清空舊段。ReferenceEntry<K, V> head = oldTable.get(oldIndex);if (head != null) {ReferenceEntry<K, V> next = head.getNext();int headIndex = head.getHash() & newMask;// Single node on listif (next == null) {//對于單個的節(jié)點的,直接插入新段中newTable.set(headIndex, head);} else {//重復(fù)使用列表末尾具有相同目標索引的連續(xù)節(jié)點序列。tail指向可重用序列中的第一個節(jié)點。ReferenceEntry<K, V> tail = head;int tailIndex = headIndex;for (ReferenceEntry<K, V> e = next; e != null; e = e.getNext()) {int newIndex = e.getHash() & newMask;if (newIndex != tailIndex) {tailIndex = newIndex;tail = e;}}//將可重用序列中的第一個節(jié)點放入新映射位置newTable.set(tailIndex, tail);//將頭尾之間的節(jié)點重新映射到新段中for (ReferenceEntry<K, V> e = head; e != tail; e = e.getNext()) {int newIndex = e.getHash() & newMask;ReferenceEntry<K, V> newNext = newTable.get(newIndex);//拷貝當前節(jié)點作為新的頭節(jié)點,并將映射位置的頭節(jié)點鏈接到當前節(jié)點e的next。ReferenceEntry<K, V> newFirst = copyEntry(e, newNext);if (newFirst != null) {//如果拷貝的新頭節(jié)點不為null,則set到新段中newTable.set(newIndex, newFirst);} else {//否則,刪除eremoveCollectedEntry(e);newCount--;}}}}}table = newTable;this.count = newCount;}

其中,對段節(jié)點的重映射邏輯如圖所示:
在這里插入圖片描述
這里需要留意的是Cache在重映射時,是將后續(xù)節(jié)點作為頭節(jié)點插入到?jīng)_突位中,即首插入。故,新表映射的鏈路順序與舊表會有比較大的區(qū)別。

http://m.aloenet.com.cn/news/1599.html

相關(guān)文章:

  • 用asp做網(wǎng)站span友情鏈接大全
  • 音頻網(wǎng)站開發(fā)湖南營銷型網(wǎng)站建設(shè)
  • 閑魚網(wǎng)站建設(shè)費用核心關(guān)鍵詞是什么意思
  • 海南網(wǎng)站建設(shè)推廣線上營銷渠道有哪些
  • 嘉興網(wǎng)站系統(tǒng)總部外鏈工廠
  • web 網(wǎng)站做甘特圖教育機構(gòu)排名
  • 自己做國際網(wǎng)站網(wǎng)絡(luò)營銷管理
  • 有沒有靠譜的推廣平臺手機優(yōu)化軟件哪個好用
  • 怎么用ps做網(wǎng)站圖片nba排名西部和東部
  • 做網(wǎng)站搜索如何顯示官網(wǎng)高端網(wǎng)站定制開發(fā)
  • 蘭州網(wǎng)站建設(shè) 冰雨品牌推廣的具體方法
  • 站長平臺百度百度直播
  • 新手學(xué)做網(wǎng)站pdf手競價網(wǎng)官網(wǎng)
  • 網(wǎng)頁設(shè)計專業(yè)大學(xué)排名網(wǎng)站seo最新優(yōu)化方法
  • 網(wǎng)站選擇理由描述百度seo排名原理
  • 秦皇島網(wǎng)站建設(shè)哪家好天津做優(yōu)化好的公司
  • 博羅做網(wǎng)站報價軟文模板
  • 舞鋼市做網(wǎng)站開發(fā)的公司網(wǎng)絡(luò)營銷的目的是
  • 網(wǎng)站建設(shè)字圖search搜索引擎
  • 武漢手游網(wǎng)站開發(fā)推廣賺錢項目
  • 成都個人網(wǎng)站seo企業(yè)建站系統(tǒng)
  • 建站平臺在線提交表格數(shù)字營銷工具
  • 微信網(wǎng)站 手機網(wǎng)站互聯(lián)網(wǎng)廣告平臺排名
  • 私人網(wǎng)站服務(wù)器搭建怎么建立一個屬于自己的網(wǎng)站
  • 官方網(wǎng)站打不開怎么回事廣州企業(yè)推廣
  • 成都網(wǎng)站改版優(yōu)化寧波seo推廣咨詢
  • 網(wǎng)站單個頁面seo公司網(wǎng)站推廣
  • 怎樣做php網(wǎng)站初學(xué)seo網(wǎng)站推廣需要怎么做
  • 公司網(wǎng)站建設(shè)有用嗎谷歌優(yōu)化seo
  • 做折扣的網(wǎng)站有哪些定制網(wǎng)站