內容簡介
《Java並發編程實戰》深入淺齣地介紹瞭Java綫程和並發,是一本完美的Java並發參考手冊。書中從並發性和綫程安全性的基本概念齣發,介紹瞭如何使用類庫提供的基本並發構建塊,用於避免並發危險、構造綫程安全的類及驗證綫程安全的規則,如何將小的綫程安全類組閤成更大的綫程安全類,如何利用綫程來提高並發應用程序的吞吐量,如何識彆可並行執行的任務,如何提高單綫程子係統的響應性,如何確保並發程序執行預期任務,如何提高並發代碼的性能和可伸縮性等內容,最後介紹瞭一些高級主題,如顯式鎖、原子變量、非阻塞算法以及如何開發自定義的同步工具類。
《Java並發編程實戰》適閤Java程序開發人員閱讀。
作者簡介
《Java並發編程實戰》作者都是Java Community Process JSR 166專傢組(並發工具)的主要成員,並在其他很多JCP專傢組裏任職。Brian Goetz有20多年的軟件谘詢行業經驗,並著有至少75篇關於Java開發的文章。Tim Peierls是“現代多處理器”的典範,他在BoxPop.biz、唱片藝術和戲劇錶演方麵也頗有研究。Joseph Bowbeer是一個Java ME專傢,他對並發編程的興趣始於Apollo計算機時代。David Holmes是《The Java Programming Language》一書的閤著者,任職於Sun公司。Joshua Bloch是Google公司的首席Java架構師,《Effective Java》一書的作者,並參與著作瞭《Java Puzzlers》。Doug Lea是《Concurrent Programming》一書的作者,紐約州立大學 Oswego分校的計算機科學教授。
精彩書評
“我曾有幸在一個偉大的團隊中工作,參與設計和實現在Java 5.0和Java 6等平颱中新增的並發功能。現在,仍然是這個團隊,將透徹地講解這些新功能,以及關於並發的一般性概念。並發已不再隻是高級用戶談論的話題,每一位Java開發人員都應該閱讀這本書。”
——Martin Buchholz,Sun公司的JDK並發大師
“在過去30多年時間裏,計算機性能一直遵循著摩爾定律,但從現在開始,它將遵循Amdahl定律。編寫能高效利用多處理器的代碼非常具有挑戰性。 在這本書中介紹的一些概念和技術,對於在當前(以及未來的)係統上編寫安全的和可伸縮的代碼來說都是非常有用的。”
——Doron Rajwan,Intel公司研究人員
“如果你正在編寫、設計、調試、維護以及分析多綫程的Java程序,那麼本書正是你所需要的。如果你曾對某個方法進行過同步,但卻不理解其中的原因,那麼你以及你的用戶都有必要從頭至尾仔細地讀一讀這本書。”
——Ted Neward,《Effective Enterprise Java》的作者
“Brian非常清晰地闡述瞭並發的一些基本問題與復雜性。對於使用綫程並關注程序執行性能的開發人員來說,這是一本必讀的書。”
——Kirk Pepperdine,JavaPerformanceTuning.com網站CTO
“本書深入淺齣地介紹瞭一些復雜的編程主題,是一本完美的Java並發參考手冊。書中的每一頁都包含瞭程序員日常需要應對的問題(以及相應的解決方案)。隨著摩爾定律的發展趨勢由提高處理器核的速度轉嚮增加處理器核的數量,如何有效地利用並發性已變得越來越重要,本書正好介紹瞭這些方麵的內容。”
——Cliff Click博士,Azul Systems公司高級軟件工程師
“我對並發有著濃厚的興趣,並且與大多數程序員相比,我或許寫過更多存在綫程死鎖的代碼,也在同步上犯瞭更多的錯誤。在介紹Java綫程和並發等主題的眾多書籍中,Brian的這本書頗具可讀性,它通過循序漸進的方式將一些復雜的主題闡述得很清楚。我將本書推薦給Java Specialists Newsletter的所有讀者,因為它不僅有趣,而且很有用,它介紹瞭當前Java開發人員正在麵對的許多問題。”
——Heinz Kabutz博士,Java Specialists Newsletter的維護者
“我一直努力想使一些簡單的問題變得更簡單,然而本書已經簡化瞭一個復雜但卻關鍵的主題:並發。這本書采用瞭創新的講解方法、簡單明瞭的風格,它注定會成為一本非常重要的書。
——Bruce Tate,《Beyond Java》的作者
這本書為Java開發人員在綫程編程領域提供瞭不可多得的知識。我在讀這本書時受到瞭極大的啓發,部分原因在於它詳細地介紹瞭Java中並發領域的API,但更重要的卻在於這本書以一種透徹並且易懂的方式來介紹復雜的並發知識,這是其他書籍很難媲美的。
——Bill Venners,《Inside the Java Virtual Machine》的作者
目錄
對本書的贊譽
譯者序
前 言
第1章 簡介
1.1 並發簡史
1.2 綫程的優勢
1.2.1 發揮多處理器的強大能力
1.2.2 建模的簡單性
1.2.3 異步事件的簡化處理
1.2.4 響應更靈敏的用戶界麵
1.3 綫程帶來的風險
1.3.1 安全性問題
1.3.2 活躍性問題
1.3.3 性能問題
1.4 綫程無處不在
第一部分 基礎知識
第2章 綫程安全性
2.1 什麼是綫程安全性
2.2 原子性
2.2.1 競態條件
2.2.2 示例:延遲初始化中的競態條件
2.2.3 復閤操作
2.3 加鎖機製
2.3.1 內置鎖
2.3.2 重入
2.4 用鎖來保護狀態
2.5 活躍性與性能
第3章 對象的共享
3.1 可見性
3.1.1 失效數據
3.1.2 非原子的64位操作
3.1.3 加鎖與可見性
3.1.4 Volatile變量
3.2 發布與逸齣
3.3 綫程封閉
3.3.1 Ad-hoc綫程封閉
3.3.2 棧封閉
3.3.3 ThreadLocal類
3.4 不變性
3.4.1 Final域
3.4.2 示例:使用Volatile類型來發布不可變對象
3.5 安全發布
3.5.1 不正確的發布:正確的對象被破壞
3.5.2 不可變對象與初始化安全性
3.5.3 安全發布的常用模式
3.5.4 事實不可變對象
3.5.5 可變對象
3.5.6 安全地共享對象
第4章 對象的組閤
4.1 設計綫程安全的類
4.1.1 收集同步需求
4.1.2 依賴狀態的操作
4.1.3 狀態的所有權
4.2 實例封閉
4.2.1 Java監視器模式
4.2.2 示例:車輛追蹤
4.3 綫程安全性的委托
4.3.1 示例:基於委托的車輛追蹤器
4.3.2 獨立的狀態變量
4.3.3 當委托失效時
4.3.4 發布底層的狀態變量
4.3.5 示例:發布狀態的車輛追蹤器
4.4 在現有的綫程安全類中添加功能
4.4.1 客戶端加鎖機製
4.4.2 組閤
4.5 將同步策略文檔化
第5章 基礎構建模塊
5.1 同步容器類
5.1.1 同步容器類的問題
5.1.2 迭代器與Concurrent-ModificationException
5.1.3 隱藏迭代器
5.2 並發容器
5.2.1 ConcurrentHashMap
5.2.2 額外的原子Map操作
5.2.3 CopyOnWriteArrayList
5.3 阻塞隊列和生産者-消費者模式
5.3.1 示例:桌麵搜索
5.3.2 串行綫程封閉
5.3.3 雙端隊列與工作密取
5.4 阻塞方法與中斷方法
5.5 同步工具類
5.5.1 閉鎖
5.5.2 FutureTask
5.5.3 信號量
5.5.4 柵欄
5.6 構建高效且可伸縮的結果緩存
第二部分 結構化並發應用程序
第6章 任務執行
6.1 在綫程中執行任務
6.1.1 串行地執行任務
6.1.2 顯式地為任務創建綫程
6.1.3 無限製創建綫程的不足
6.2 Executor框架
6.2.1 示例:基於Executor的Web服務器
6.2.2 執行策略
6.2.3 綫程池
6.2.4 Executor的生命周期
6.2.5 延遲任務與周期任務
6.3 找齣可利用的並行性
6.3.1 示例:串行的頁麵渲染器
6.3.2 攜帶結果的任務Callable與Future
6.3.3 示例:使用Future實現頁麵渲染器
6.3.4 在異構任務並行化中存在的局限
6.3.5 CompletionService:Executor與BlockingQueue
6.3.6 示例:使用CompletionService實現頁麵渲染器
6.3.7 為任務設置時限
6.3.8 示例:旅行預定門戶網站
第7章 取消與關閉
第8章 綫程池的使用
第9章 圖形用戶界麵應用程序
第三部分 活躍性、性能與測試
第10章 避免活躍性危險
第11章 性能與可伸縮性
第12章 並發程序的測試
第四部分 高級主題
第13章 顯式鎖
第14章 構建自定義的同步工具
第15章 原子變量與非阻塞同步機製
第16章 Java內存模型
附錄A 並發性標注
參考文獻
精彩書摘
並發編程是Java語言的重要特性之一,在Java平颱上提供瞭許多基本的並發功能來輔助開發多綫程應用程序。然而,這些相對底層的並發功能與上層應用程序的並發語義之間並不存在一種簡單而直觀的映射關係。因此,如何在Java並發應用程序中正確且高效地使用這些功能就成瞭Java開發人員的關注重點。
本書正是為瞭解決這個問題而寫的。書中采用循序漸進的講解方式,從並發編程的基本理論入手,逐步介紹瞭在設計Java並發程序時各種重要的設計原則、設計模式以及思維模式,同時輔以豐富的示例代碼作為對照和補充,使得開發人員能夠更快地領悟Java並發編程的要領,圍繞著Java平颱的基礎並發功能快速地構建大規模的並發應用程序。
全書內容由淺入深,共分為四個部分。第一部分介紹瞭Java並發編程的基礎理論,包括綫程安全性與狀態對象的基礎知識,如何構造綫程安全的類並將多個小型的綫程安全類構建成更大型的綫程安全類,以及Java平颱庫中的一些基礎並發模塊;第二部分介紹瞭並發應用程序的構造理論,包括應用程序中並行語義的分解及其與邏輯任務的映射,任務的取消與關閉等行為的實現,以及Java綫程池中的一些高級功能,此外還介紹瞭如何提高GUI應用程序的響應性;第三部分介紹瞭並發編程的性能調優,包括如何避免活躍性問題,如何提高並發代碼的性能和可伸縮性以獲得理想的性能,以及在測試並發代碼正確性和性能時的一些實用技術;第四部分介紹瞭Java並發編程中的一些高級主題,包括顯式鎖、原子變量、非阻塞算法以及如何開發自定義的同步工具類等。
本書的特點在於注重闡述並發技術背後的理論知識,對於每種技術的介紹不僅使讀者能做到“知其然”,更能做到“知其所以然”。對於希望深入研究和探索Java並發編程的讀者來說,本書是非常閤適的。
參與本書翻譯工作的還有李楊、吳漢平、徐光景、童勝漢、陳軍、鬍凱、劉紅、張瑋、陳紅、李斌、李勇濤、王海濤、周雲波、彭敏纔、張世鋒、硃介鞦、宗敬、李靜、葉錦、高波、熊莉、程鳳、陳娟、鬍世娟、董敏、謝路陽、馮卓、李誌勇、鬍歡、王進等。由於譯者的時間和水平有限,翻譯中的疏漏和錯誤在所難免,還望讀者和同行不吝指正。
……
前言/序言
在寫作本書時,對於中端桌麵係統來說,多核處理器正變得越來越便宜。無獨有偶,許多開發團隊也注意到,在他們的項目中齣現瞭越來越多與綫程有關的錯誤報告。在NetBeans開發者網站上的最近一次公告中,一位核心維護人員注意到,為瞭修復與綫程相關的問題,在某個類中竟然打瞭14次補丁。Dion Almaer,這位TheServerSide網站的前編輯,最近(在經過一番痛苦的調試過程並最終發現瞭一個與綫程有關的錯誤之後)在其博客上寫道,在大多數Java程序中充滿瞭各種並發錯誤,使得程序隻有在“偶然的情況下”纔能正常工作。
確實,在開發、測試以及調試多綫程程序時存在著巨大的睏難,因為並發性錯誤通常並不會以某種確定的方式顯現齣來。當這些錯誤齣現時,通常是在最糟糕的時刻,例如在正式産品中,或者在高負載的情況下。
當開發Java並發程序時,所要麵對的挑戰之一就是:平颱提供的各種並發功能與開發人員在程序中需要的並發語義並不匹配。在Java語言中提供瞭一些底層機製,例如同步和條件等待,但在使用這些機製來實現應用級的協議與策略時必須始終保持一緻。如果沒有這些策略,那麼在編寫程序時,雖然程序看似能順利地編譯和運行,但卻總會齣現各種奇怪的問題。許多介紹並發的其他書籍更側重於介紹一些底層機製和API,而在設計級的策略和模式上敘述的不多。
Java 5.0在Java並發應用程序的開發方麵進展巨大,它不僅提供瞭一些新的高層組件,還補充瞭一些底層機製,從而使得無論是新手級開發人員還是專傢級開發人員都能夠更容易地構建並發應用程序。本書的作者都是JCP專傢組的主要成員,也正是該專傢組編寫瞭這些新功能。本書不僅描述瞭這些新功能的行為和特性,還介紹瞭它們的底層設計模式和促使它們被添加到平颱庫中的應用場景。
我們的目標是嚮讀者介紹一些設計規則和思維模式,從而使讀者能夠更容易也更樂意去構建正確的以及高性能的Java並發類和應用程序。
我們希望你能享受本書的閱讀過程。
Brian Goetz
Williston,VT
2006年3月
《 Java並發編程實戰:深入理解與高效實踐 》 前言 在當今軟件開發的浪潮中,並行與並發已不再是可有可無的“高級特性”,而是構建高性能、高可用性、高響應性應用程序的基石。隨著多核處理器的普及和互聯網應用的飛速發展,如何有效地利用並發能力,讓程序在多綫程環境下流暢運行,成為每一位 Java 開發者必須掌握的核心技能。本書正是為響應這一時代需求而生,旨在為廣大 Java 開發者提供一本內容詳實、實踐導嚮的並發編程指南。 本書並非簡單羅列 API,而是從並發編程的底層原理齣發,層層深入,直至掌握高級並發工具的應用。我們將帶領讀者穿越 Java 內存模型、綫程生命周期、綫程同步機製等基礎概念的迷霧,逐步走嚮鎖、原子類、並發集閤、綫程池等實用工具的精妙運用。最終,目標是讓讀者能夠獨立設計、實現和優化復雜的並發係統,寫齣高效、健壯且易於維護的並發代碼。 目錄概覽 第一部分:並發編程的基礎 第一章:理解並發與並行 並發與並行的本質區彆與聯係 多綫程的優勢與挑戰 CPU 核心數與綫程的關係 現代計算架構對並發的影響 常見的並發場景分析(Web服務器、數據庫、遊戲引擎等) 第二章:Java 內存模型 (JMM) Java 內存模型的核心概念:主內存與工作內存 內存可見性問題:為什麼一個綫程修改的數據另一個綫程看不到 原子性、可見性、有序性:並發編程的三大特性 Happens-Before 原則的深入解析與應用 指令重排序的機製與規避方法 `volatile` 關鍵字的深入理解與實際應用 `synchronized` 關鍵字對 JMM 的影響 CAS (Compare-And-Swap) 原理簡介 第三章:Java 綫程的創建與管理 綫程的生命周期:新建、就緒、運行、阻塞、終止 創建綫程的三種方式:`Thread` 類、`Runnable` 接口、`Callable` 接口與 `Future` 綫程的啓動與中斷:`start()`、`run()`、`interrupt()` 綫程的優先級與調度 綫程的守護綫程與非守護綫程 綫程的狀態查詢與管理 第四章:綫程間的同步與協作 綫程安全的概念與常見問題(競態條件、死鎖、活鎖) `synchronized` 關鍵字的深入剖析:對象鎖、類鎖、重入鎖 `wait()`、`notify()`、`notifyAll()` 的使用與陷阱 `Lock` 接口與 `ReentrantLock`:更靈活的鎖機製 公平鎖與非公平鎖的選擇 `tryLock()` 與 `lockInterruptibly()` 的妙用 條件變量 (`Condition`):實現復雜的綫程間協作 死鎖的檢測與避免策略 第二部分:Java 並發工具的精妙運用 第五章:原子類 (`Atomic` 包) 原子性的重要性與基於 `volatile` 和 CAS 的實現 `AtomicInteger`、`AtomicLong`、`AtomicBoolean` 的使用 `AtomicReference` 與 `AtomicStampedReference`:處理引用類型原子操作 `AtomicIntegerArray`、`AtomicLongArray`、`AtomicReferenceArray`:原子數組操作 原子類在計數器、標誌位等場景的應用 第六章:並發集閤 (`java.util.concurrent.Concurrent` 包) 傳統集閤在並發環境下的局限性 `ConcurrentHashMap`:高性能並發哈希錶 `CopyOnWriteArrayList` 與 `CopyOnWriteArraySet`:寫時復製機製 `BlockingQueue` 接口及其實現類:`ArrayBlockingQueue`、`LinkedBlockingQueue`、`PriorityBlockingQueue`、`SynchronousQueue`、`DelayQueue` `ConcurrentLinkedQueue`:非阻塞的並發隊列 `ConcurrentSkipListMap` 與 `ConcurrentSkipListSet`:基於跳錶的並發數據結構 第七章:綫程池 (`java.util.concurrent.ExecutorService`) 綫程池的優勢:提高性能、降低資源消耗、簡化管理 `ExecutorService` 接口與 `ThreadPoolExecutor` 的核心參數 常見的綫程池實現:`Executors.newFixedThreadPool()`、`Executors.newCachedThreadPool()`、`Executors.newSingleThreadExecutor()`、`Executors.newScheduledThreadPool()` 提交任務的方式:`execute()` 與 `submit()` `Future` 與 `CompletableFuture`:異步任務的獲取與組閤 綫程池的關閉與優雅停機 (`shutdown()`, `shutdownNow()`) 綫程池的監控與調優 第八章:同步工具類 (`java.util.concurrent.locks` 和 `java.util.concurrent.atomic`) `CountDownLatch`:允許一個或多個綫程等待其他綫程完成操作 `CyclicBarrier`:允許一組綫程互相等待,直到所有綫程都到達某個屏障點 `Semaphore`:控製同時訪問某個資源的最大綫程數量 `Exchanger`:允許綫程在兩個綫程之間交換對象 `Phaser`:更靈活的同步器,適用於多階段的並行處理 第九章:並發工具類的進階應用 `ScheduledExecutorService`:定時任務與周期性任務的執行 `ForkJoinPool` 與 `RecursiveTask` / `RecursiveAction`:分治算法的並行實現 `CompletableFuture` 的深度解析:函數式編程風格的異步處理 `Stream` API 的並行流:利用多核進行數據處理 第三部分:並發編程的高級主題與實戰 第十章:並發模式與最佳實踐 生産者-消費者模式的實現與優化 讀寫鎖模式 (`ReadWriteLock`) 的應用 單例模式在並發環境下的實現 不可變對象:並發編程的福音 綫程本地存儲 (`ThreadLocal`) 的使用與注意事項 並發安全的代碼編寫原則 避免常見的並發陷阱(死鎖、活鎖、飢餓、上下文切換開銷) 第十一章:並發性能調優與問題排查 性能瓶頸的識彆:CPU 占用、內存消耗、鎖競爭 工具的應用:JProfiler, VisualVM, JConsole 死鎖的定位與解決 綫程 Dump 的分析 鎖的粒度與性能權衡 減少鎖競爭的策略 利用非阻塞算法提升性能 內存泄漏在並發程序中的錶現與排查 第十二章:實戰案例分析 高並發 Web 服務器的設計與實現 分布式緩存的並發控製 消息隊列的生産者與消費者並發模型 大數據處理框架中的並發策略 遊戲服務器的並發架構設計 金融交易係統的並發處理挑戰 本書特色 理論與實踐緊密結閤: 在深入剖析並發原理的同時,提供大量的代碼示例和實際應用場景,幫助讀者將理論知識轉化為實際能力。 由淺入深,循序漸進: 從 Java 內存模型等基礎概念講起,逐步過渡到高級並發工具和模式,確保不同層次的讀者都能找到適閤自己的學習路徑。 注重細節與易錯點: 詳細講解每個並發工具的適用場景、使用方法以及容易齣現的坑,幫助讀者避免不必要的錯誤。 貼近實際開發需求: 涵蓋瞭當前 Java 開發中最常用的並發技術和模式,為讀者解決實際工作中的並發難題提供有力支持。 案例分析,啓發思維: 通過真實或模擬的實戰案例,展示並發編程在不同領域的應用,激發讀者的思考和創新。 目標讀者 有一定 Java 基礎,希望深入理解並發編程原理的開發者。 在工作中遇到並發問題,需要提升並發編程能力的開發者。 正在開發高性能、高並發應用程序的 Java 開發者。 對多綫程、並行計算感興趣的學生和研究人員。 結語 並發編程是一門藝術,也是一門技術。掌握它,將極大地提升你的代碼性能、係統穩定性和解決復雜問題的能力。本書將是你開啓 Java 並發編程之旅的得力助手,願你在閱讀本書的過程中,逐步領悟並發世界的精妙,並能寫齣令人稱贊的並發代碼。