在Java開發中,單例模式是一種常用的設計模式,用來確保一個類別只有一個實例物件。然而,在多執行緒環境下,使用單例模式可能會引發執行緒安全性問題,進而影響程式的效能和正確性。那麼,如何在Java中使單例bean線程安全並具有更好的性能? php小編魚仔將在以下幾個方面為大家介紹與解答。
我正在嘗試與多個使用者測試下面的程式碼。但由於該類別是由 spring 管理的單例,因此只有一個已建立的對象,並且多個執行緒試圖存取同一個對象。
由於輸出字串不一致。嘗試透過在 applogger 方法中使用 synchronized 關鍵字來解決此問題。它正在按預期工作。但我們需要在性能上做出妥協。
如何在多執行緒環境中處理單例bean,並透過實例變數(stringbuilder)修改來獲得更好的效能?
編輯程式碼,新增aggregatelogger方法。此方法會將字串聚合到已在類別層級宣告的現有 stringbuilder,以便 stringbuilder 將具有來自 applogger 和aggregatelogger 方法的聚合日誌。
@Aspect @Slf4j @Component public class A{ private StringBuilder builder = new StringBuilder(); public StringBuilder getSb(){ return builder; } public void appendToSb(String s){ builder.append(s); } @Around("@annotation(execTimeLogger)") public Object appLogger(ProceedingJointPoint pjp){ long startTime = xxx; Object object = pjp.proceed(); long endTime = xxx; String str = "Hello"; appendToSb(str); return object; } @Around("@annotation(logger)") public Object aggregateLogger(ProceedingJointPoint pjp){ long startTime = xxx; Object object = pjp.proceed(); long endTime = xxx; String str = "World"; appendToSb(str); log.info(getSb().toString()); // o/p will be Aggregated Log getSb().setLength(0); return object; } }
你的設計是錯的,請原諒我這麼直率。即使在您想要記錄的一項業務事務中,也可能有多個應用程式層在多個執行緒中執行多項操作。為什麼所有這些都必須在一條日誌訊息中?通常,您會使用某種客戶和/或交易 ID 或任何正確標識您想要追蹤和記錄的邏輯實體的內容來記錄所有訊息。大多數日誌記錄框架使用某種來映射診斷上下文 (MDC)那。無論您登入控制台或資料庫或日誌聚合器(如 Logstash 或 Graylog),您都可以按您感興趣的實體或交易進行搜尋、過濾和聚合,找到所有對應的日誌訊息。無需將它們全部放入一條日誌訊息中。
當然,您可以利用方面來進行日誌記錄,而不是用日誌語句污染您的核心程式碼。分解出像日誌記錄這樣的橫切關注點是 AOP 的主要優點之一。但你應該做對。因此,您的單例方面要么使用 MDC,要么在某種映射中進行自己的簿記。我建議使用您的日誌框架已經提供的工具,並讓方面專注於它最擅長的事情,即攔截正確的連接點。
由於效能也是您關心的問題之一,因此您可能希望將日誌框架配置為非同步日誌,從而使您的應用程式更快、更快回應。通常,記錄到檔案也比記錄到控制台更快。也許這個 GitHub 儲存庫除了我們在這裡討論的內容之外,其有趣的自述文件和 JMH 基準測試還為您提供了有趣的資訊。如果您碰巧會說德語,幾天前在 此 Heise.de 博客。這篇文章的德語內容基本上與英語自述內容相同,我只是想提供我的來源。
無論如何,當使用非同步日誌記錄時,日誌聚合 ID 在多執行緒上下文中變得更加重要。
以上是如何在java中使單例bean線程安全並具有更好的性能?的詳細內容。更多資訊請關注PHP中文網其他相關文章!