主頁 > 軟體工程 > 為Java中的多執行緒應用程式提供每日更新快取的最佳實踐

為Java中的多執行緒應用程式提供每日更新快取的最佳實踐

2022-01-17 06:54:27 軟體工程

在我的應用程式中,我希望有一個快取,該快取將通過昂貴的操作每天更新(例如,從遠程獲取并在本地計算)。這個想法是每天,它將獲取并計算今天的最新快取。在今天的任何時候,任何執行緒都應該能夠讀取/寫入每日快取。當昂貴的操作每天運行時提供舊資料是可以的,并且不應該在任何時候阻止任何請求。

我撰寫了一個簡單的代碼來說明這個想法,但不確定它是否是最佳實踐,甚至在多執行緒方面是否正確。例如,

  • volatile必需的嗎?
  • 如果在 get 或 put 中間完成快取重新分配會發生什么。

任何建議將不勝感激!

public class DailyCache {
    private volatile ConcurrentHashMap<String, String> cache;

    public DailyCache() {
        cache = expensiveCalculation();
        Executors.newScheduledThreadPool(1)
                 .scheduleAtFixedRate(() -> cache = expensiveCalculation(), 1, 1, TimeUnit.DAYS);
    }

    public String get(String key) {
        return cache.get(key);
    }

    public void put(String key, String value) {
        cache.put(key, value);
    }

    public ConcurrentHashMap<String, String> expensiveCalculation() {
        // an expensive operation to fetch the cache for today
    }
}

uj5u.com熱心網友回復:

執行服務

首先,您需要捕獲從 call 回傳的參考Executors.newScheduledThreadPool(1)您必須將該參考存盤在您的應用程式中的某個位置,以便最終關閉。如果你忽略了關閉一個執行器服務,它的后臺執行緒池可能會在你的應用退出后繼續運行,就像一個僵尸???♂?。

順便說一下,對于單執行緒執行器服務,呼叫便捷方法Executors.newSingleThreadExecutor

替換條目

如果您使用的是執行緒安全集合,那么我會在更新期間替換單個元素。您是否需要同時替換所有地圖條目?如果是這樣,請在您的問題中這么說。

如果您沒有理由更換整個地圖,請更改您的代碼以將您的標記cachefinal. 如果您在第一次嘗試訪問它之前就確定了地圖的存在,并且您從不替換它,則無需將其標記為volatile.

另一件事:通常最好使您的欄位成為最適合的型別。所以在這種情況下,ConcurrentMap而不是將自己鎖定在ConcurrentHashMap.

public class DailyCache {
    private final ConcurrentMap< String, String > cache;
    private final ScheduledExecutorService ses;

    public DailyCache() {
        this.cache = new ConcurrentHashMap<>() ;
        this.expensiveCalculation();
        this.ses = Executors.newSingleThreadExecutor() ; 
        this.ses.scheduleAtFixedRate(() -> cache = expensiveCalculation(), 1, 1, TimeUnit.DAYS );
    }

    public String get( String key ) {
        return this.cache.get( key );
    }

    public void put( String key, String value) {
        this.cache.put( key, value );
    }

    public void expensiveCalculation() {
        // A series of expensive operations to replace each element/entry of the `Map` cache.
    }

    public void shutdown() {
        // Gracefully shut down the scheduled executor service held in var `ses`. 
    }
}

這種入口替換方法的一個優點是新資料可以更快地到達用戶手中,呼叫代碼可以使用早期的替換,而后面的替換尚未完成。

更換地圖

volatile

如果您有理由一次全部替換整個映射,而不是替換單個條目,那么您應該將cache宣告設為非final, 和volatile

public class DailyCache {
    private volatile ConcurrentMap< String, String > cache;

但我更喜歡不同的方法。由于具體定義的變化,以及一般并發的復雜性,我預計volatile關鍵字并不是所有程式員都清楚地理解。

AtomicReference

所以我會使用一個AtomicReference物件來保存對當前地圖物件的參考。看到那個AtomicReference宣告應該會讓你的意圖對另一個程式員很明顯。

AnAtomicReference是物件參考的執行緒安全持有者。

  • var ? reference ? object
    With a conventional reference, such as the cache variable seen above, we are one step away from the map object: The cache variable holds a reference which at runtime takes us to the ConcurrentMap object floating within the heap somewhere.
  • var ? reference ? object ? reference ? object
    With an AtomicReference, we are two steps away from the desired object. The cache variable seen below is a reference to an object whose content is the reference to yet another object.

AnAtomicReference一開始想起來有點奇怪,因為在 Java 中我們認為像cache上面這樣的變數物件,即使我們知道它離物件只有一步之遙。相比之下,anAtomicReference使我們非常清楚我們正在操作對包含對物件的參考的物件的參考。例如,注意下面的.get().get(…)and.get().put(…)呼叫。

public class DailyCache {
    private final AtomicReference < ConcurrentMap< String, String > > cache;

這是完整的課程,為AtomicReference.

public class DailyCache {
    private final AtomicReference < ConcurrentMap< String, String > > cache;
    private final ScheduledExecutorService ses;

    public DailyCache() {
        this.cache = new AtomicReference<>( new ConcurrentHashMap< String, String > () ) ;
        this.expensiveCalculation() ;
        this.ses = Executors.newSingleThreadExecutor() ; 
        this.ses.scheduleAtFixedRate(() -> cache = expensiveCalculation(), 1, 1, TimeUnit.DAYS );
    }

    public String get( String key ) {
        return this.cache.get().get( key );
    }

    public void put( String key, String value) {
        this.cache.get().put( key, value );
    }

    public void expensiveCalculation() {
        ConcurrentMap< String, String > concurrentMap = … // An expensive operation to produce a new `ConcurrentMap`.
        this.cache.set( concurrentMap ) ;
    }

    public void shutdown() {
        // Gracefully shut down the scheduled executor service held in var `ses`. 
    }
}

uj5u.com熱心網友回復:

要回答您的問題:

問:這是“最佳實踐”嗎

沒有最佳實踐如果您還沒有這樣做,請花時間閱讀。

這個問題無法回答……甚至沒有意義。

提示:是時候從你的詞匯表中洗掉“最佳實踐”了......并開始質疑那些告訴你某事是“最佳實踐”的人的智慧。

問:volatile需要嗎?

或許。這取決于是否可以cache更改參考。

  • 如果可能,那么volatile是必需的。
  • 如果不可能,則volatile 可能不需要。但在這種情況下,您應該將變數宣告為final. 如果你這樣做,那么 JLS 保證所有執行緒都會看到正確的變數值。

在您的代碼中,您似乎正在定期為cache. 如果是這樣,那么它需要是volatile,或者您需要其他方式來確保所有作業執行緒都看到更新的cache值。(還有其他方法......但這開始有過早優化的味道。)

問:如果在 get 或 put 程序中完成了快取重新分配,會發生什么情況。

如果getorput呼叫在賦值之前開始,那么它們肯定會在舊快取上進行操作。如果不是,則不是,這將取決于對 fetch 是cache發生在分配之前還是之后。這是不可預測的。


還有一件事你似乎沒有考慮過。你說:

當昂貴的操作每天運行時提供舊資料是可以的,并且不應該在任何時候阻止任何請求。

但是您還沒有說在構建新快取時更新舊快取是否可以(或不可以)。例如,考慮以下事件序列:

  1. 開始重建快取
  2. 快取重建器更新新快取中的 key1 -> value1
  3. 主應用程式讀取并更新舊快取中的 key1 -> value2
  4. 快取被替換。

現在我們使用新快取運行應用程式,但新快取包含 key1 的 value1,它比最近使用的 value (value2) 更舊。

如果這破壞了您的應用程式,那么您需要一種方法來解決它。會有一些方法......但這將取決于您沒有提到的應用程式邏輯的各個方面。例如,主應用程式將執行put操作的場景。

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/412302.html

標籤:

上一篇:在共享物件上進行隔離多執行緒計算的好模式是什么?

下一篇:為什么即使在單執行緒情況下也不使用同步的ArrayList?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more