资讯动态

java-design-patterns 實戰:深入解析 Active Object 主動式物件模式與 Java 非同步併發架構

发布时间:2026/10/3 2:19:04 来源:尧图企业网站定制
示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载主動式物件模式Active Object Design Pattern將「方法執行」與「方法呼叫」徹底脫鉤讓每個物件駐留在自己的控制執行緒中以非同步方法呼叫與請求排程器引入併發能力——這正是本倉庫 java-design-patterns 中active-object模組的核心主題。本文將以 localization/zh-TW/active-object/README.md 為骨架結合倉庫內的完整原始碼、測試案例與 UML 圖帶你掌握該模式從概念到實作、從執行流程到測試驗證的完整脈絡。模式目的不需要 synchronized 的自動同步主動式物件模式要解決的根本問題是在多執行緒環境下如何讓物件擁有自己的執行緒控制權同時對外只暴露 API、不暴露執行細節並避免直接操作執行緒與共享狀態帶來的複雜度。實作主動式物件模式的類別將包含自我同步機制而無需使用synchronized方法。每個物件內部持有一條「請求佇列」與一個「專屬控制執行緒」呼叫方把方法呼叫包裝成任務丟進佇列控制執行緒依序取出並執行——同步問題因此被「佇列化」天然化解而非依賴鎖。從 App.java 的類別註解可以印證這一設計意圖The Active Object pattern helps to solve synchronization difficulties without using synchronized methods. The active object will contain a thread-safe data structure (such as BlockingQueue) and use to synchronize method calls by moving the logic of the method into an invocator (usually a Runnable) and store it in the DSA.即用執行緒安全的資料結構BlockingQueue取代鎖把方法邏輯搬進Runnable呼叫器後存入佇列即可完成同步。模式的六大組成元素從模式理論與 英文版 README 的說明Active Object 模式由六個元素構成元素職責Proxy代理向客戶端提供公開可呼叫的介面隱藏非同步細節Method Request介面定義對主動式物件的請求Pending Requests待處理請求清單暫存客戶端發出的請求佇列Scheduler排程器決定下一個執行哪個請求Servant執行體主動式物件方法的實際實作Callback / Future回呼或變數供客戶端接收執行結果在本倉庫的精簡實作中這六個角色被濃縮進兩個類別BlockingQueueRunnable同時扮演「待處理請求佇列」與「排程器」FIFO 依序取出執行緒消費佇列即為「Servant 執行體」而公開的eat()、roam()方法即為「Proxy 介面」。從active-object/src/main/java/com/iluwatar/activeobject/目錄下的 3 個 Java 檔案可以看出這種最小化設計的取捨——刻意用 Java 標準函式庫完成全部功能沒有引入任何第三方併發框架。真實世界範例獸人比喻本文件獸人以其野性和頑強的靈魂著稱牠們的行為似乎由一個獨立的控制執行緒所驅動基於先前的動作做出反應。要實作出一個擁有自身控制執行緒、僅公開 API 而不暴露執行細節的物件就可以使用主動式物件模式。餐廳比喻英文版想像一間繁忙的餐廳——服務生負責接單卻不必親自進廚房做菜他們把訂單寫在紙條上交給調度員dispatcher調度員管理一群廚師chefs異步備餐。廚師空閒時就從佇列中取下一張訂單開始料理完成後通知服務生上菜。這裡的服務生代表客戶端執行緒調度員代表排程器廚師代表在不同執行緒中的方法執行——與主動式物件模式「方法呼叫與方法執行脫鉤」的運作方式如出一轍。用一句話概括主動式物件模式把方法執行與方法呼叫解耦以提升多執行緒應用程式的併發度與回應性。類別圖與模組結構主動式物件模組的類別結構非常精簡完整 UML 類圖見 active-object/etc/active-object.urm.pngPlantUML 原始檔位於 active-object/etc/active-object.urm.pumlActiveCreature抽象基底類別封裝請求佇列、控制執行緒與生命週期管理OrcActiveCreature的具體子類別僅需傳入名稱App示範入口建立多個生物並下達指令。模組的 Maven 配置見 active-object/pom.xml主類別為com.iluwatar.activeobject.App執行緒安全相關依賴全部來自 JDK 內建套件java.util.concurrent第三方依賴僅有 SLF4J日誌與 JUnit 5測試。程式範例從抽象基底類別到具體生物1. 抽象基底類別 ActiveCreature以下為 ActiveCreature.java 的完整實作與文件範例相比這是含生命週期管理的目前倉庫版本public abstract class ActiveCreature { private static final Logger logger LoggerFactory.getLogger(ActiveCreature.class.getName()); private BlockingQueueRunnable requests; private String name; private Thread thread; // Thread of execution. private int status; // status of the thread of execution. protected ActiveCreature(String name) { this.name name; this.status 0; this.requests new LinkedBlockingQueue(); thread new Thread(() - { boolean infinite true; while (infinite) { try { requests.take().run(); } catch (InterruptedException e) { if (this.status ! 0) { logger.error(Thread was interrupted. -- {}, e.getMessage()); } infinite false; Thread.currentThread().interrupt(); } } }); thread.start(); } public void eat() throws InterruptedException { requests.put(() - { logger.info({} is eating!, name()); logger.info({} has finished eating!, name()); }); } public void roam() throws InterruptedException { requests.put(() - logger.info({} has started to roam in the wastelands., name())); } public String name() { return this.name; } public void kill(int status) { this.status status; this.thread.interrupt(); } public int getStatus() { return this.status; } }2. 具體子類別 Orc繼承ActiveCreature的類別將自動擁有自己的控制執行緒來執行與呼叫方法。Orc只需一行建構子Orc.javapublic class Orc extends ActiveCreature { public Orc(String name) { super(name); } }3. 示範入口 App現在建立多個生物獸人命令牠們進食與漫遊牠們將在各自的控制執行緒上執行這些動作。完整程式碼見 App.javaOverride public void run() { ListActiveCreature creatures new ArrayList(); try { for (int i 0; i NUM_CREATURES; i) { creatures.add(new Orc(Orc.class.getSimpleName() i)); creatures.get(i).eat(); creatures.get(i).roam(); } Thread.sleep(1000); } catch (InterruptedException e) { logger.error(e.getMessage()); Thread.currentThread().interrupt(); } finally { for (int i 0; i NUM_CREATURES; i) { creatures.get(i).kill(0); } } }典型程式輸出三個獸人各自在獨立執行緒Thread-0/1/2上並行執行日誌交錯出現09:00:02.501 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 is eating! 09:00:02.501 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 is eating! 09:00:02.501 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 is eating! 09:00:02.504 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 has finished eating! 09:00:02.504 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 has finished eating! 09:00:02.504 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 has started to roam in the wastelands. 09:00:02.504 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 has finished eating! 09:00:02.504 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 has started to roam in the wastelands. 09:00:02.504 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 has started to roam in the wastelands.深入原始碼執行緒、佇列與生命週期如何協作從原始碼可以拆解出以下幾個關鍵設計決策ActiveCreature.java① 無界執行緒安全佇列充當排程器requests宣告為介面型別BlockingQueueRunnable實際以LinkedBlockingQueue實作。呼叫端用requests.put(...)入隊無界佇列下不會阻塞消費端用requests.take()取出——兩者皆執行緒安全這正是「不用synchronized也能同步」的關鍵。② 專屬控制執行緒建構子在thread.start()後立即啟動消費迴圈while (infinite) { requests.take().run(); }。每個ActiveCreature例項都有一條獨立執行緒因此 N 個生物就有 N 條平行執行的控制執行緒。③ 請求封裝Method Requesteat()與roam()都不是直接執行業務邏輯而是把業務邏輯包進Runnable丟入佇列。呼叫方客戶端執行緒發出呼叫後立即返回不等待執行完成——非同步化的本質就在這裡。④ 生命週期管理kill(int status)透過設定status欄位並中斷執行緒讓消費迴圈在InterruptedException中檢查status0代表正常結束其餘值會記錄錯誤然後退出迴圈並重設中斷旗標。getStatus()則對外暴露執行緒狀態供測試與偵錯使用。⑤ 日誌確認執行緒歸屬SLF4J 日誌中的[Thread-N]前綴清楚顯示每個任務實際在哪條執行緒上執行可直接驗證「每個生物都在自己的控制執行緒上動作」的設計目標。非同步呼叫的完整時序流程模式標準化的動態流程可用 active-object/etc/active-object-sequence-diagram.png 來說明——它完整呈現了 Client、Proxy、Scheduler、MethodRequest、Servant、Future 六大角色之間的互動順序流程大致為客戶端呼叫 Proxy 的公開方法 → Proxy 將呼叫包裝為 MethodRequest 提交給 Scheduler → Scheduler 依序從佇列取出請求 → Servant 在執行緒中執行方法 → 執行結果寫入 Future → 客戶端稍後從 Future 取得結果。整個過程客戶端從頭到尾不需要阻塞等待這就是「非同步」的具體體現。在本倉庫的精簡範例中Scheduler 與 Servant 由消費迴圈合併承擔而 Future 角色因範例任務沒有回傳值而被省略。測試如何驗證模式行為倉庫提供了兩份測試可直接驗證上述設計測試目錄active-object/src/test/java/com/iluwatar/activeobject/ActiveCreatureTest.java建立Orc(orc1)斷言name()回傳正確、初始getStatus()為0接著呼叫eat()、roam()後以kill(0)優雅關閉執行緒——完整覆蓋了「建立 → 下達非同步指令 → 關閉」的生命週期。AppTest.java以assertDoesNotThrow(() - App.main(new String[] {}))驗證整個示範程式可無例外地完整跑完包含執行緒建立、佇列消費與關閉流程。可用 Maven 直接執行測試驗證./mvnw -pl active-object test或直接執行主類別com.iluwatar.activeobject.App觀察並行日誌輸出。此模組依賴 SLF4J 與 Logback 提供日誌能力見 active-object/pom.xml。何時使用 Active Object 模式在 Java 中適合採用此模式的情境包括需要處理非同步任務而不阻塞主執行緒以提升效能與回應性需要以非同步方式與外部資源互動希望提升應用程式的整體回應性例如 GUI 應用程式中把長時間任務放到背景執行避免畫面凍結需要以模組化、可維護的方式管理併發任務。典型的真實應用領域包括即時交易系統交易請求非同步處理、GUI 框架背景執行長任務、遊戲程式設計併發更新遊戲狀態或 AI 計算。優點與取捨優點Benefits提升主執行緒的回應性將併發關注點封裝於物件內部外部呼叫方無需接觸執行緒細節促進程式碼組織與可維護性提供執行緒安全性避免共享狀態存取問題。取捨Trade-offs因訊息傳遞與執行緒管理而引入額外開銷並非所有併發問題都適合以此模式解決——對於需要精細控制、低延遲或大量短任務的場景佇列排程的間接成本可能不可忽視。與其他模式的關聯在 java-design-patterns 倉庫中Active Object 與以下模式密切相關可相互對照學習Command 命令模式將請求封裝為物件與 Active Object 把方法呼叫封裝為Runnable入隊的思路一致Promise 模式提供取得非同步方法呼叫結果的機制常與 Active Object 搭配使用——本範例因任務無回傳值而未使用 Future擴充回傳值時即可引入Proxy 代理模式Active Object 可使用 Proxy 來攔截方法呼叫並非同步化處理與本模組公開 API 介面的角色相互呼應。小結Active Object 模式以「佇列 專屬執行緒」取代「鎖」把同步問題轉化為排程問題是理解 Java 非同步併發的重要基石。透過本倉庫active-object模組的 3 個原始碼檔案、2 份測試與 2 張 UML 圖你已經掌握從「方法呼叫與執行脫鉤」的理論到BlockingQueue佇列化、執行緒生命週期管理、測試驗證的完整實作路徑——下一步不妨試著在此基礎上加入回傳值與 Future觀察它如何與 Promise 模式自然銜接。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐java-design-patterns 项目实战Active Object 主动对象模式——在 Java 中实现异步调用与自同步并发java design patterns 项目实战Active Object 主动对象模式——在 Java 中实现异步调用与自同步并发 本文基于 java d示例工程教程java-design-patterns 源码精读用 Active Object 模式在 Java 中实现异步并发java design patterns 源码精读用 Active Object 模式在 Java 中实现异步并发 Active Object主动对象是示例工程教程Active Object 模式实战基于 java-design-patterns 的 Java 异步方法调用与调度机制详解Active Object 模式实战基于 java design patterns 的 Java 异步方法调用与调度机制详解 本文以 java design示例工程教程上一篇500 AI Agent 行业案例库定位案例、跑通 20 个源码的完整指南下一篇Radar 任务自动化实战基于 Rube MCP 与 Composio Radar Toolkit 的 Codex Skill 完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑