本節將簡單介紹一般的線程模型,Netty 中如何使用指定的線程模型,以及Netty 過去不同的版本中使用的線程模型。你會更好的理解不同的線程模型的所有利弊。
一個線程模型指定代碼執行,給開發人員如何執行他們代碼的信息。這很重要,因為它允許開發人員事先知道如何保護他們的代碼免受并發執行的副作用。若沒有這個知識背景,即使是最好的開發人員都只能是碰運氣,希望到最后都能這么幸運,但這幾乎是不可能的。進入更多的細節之前,提供一個更好的理解主題的回顧這些天大多數應用程序做什么。
大多數現代應用程序使用多個線程調度工作,因此讓應用程序使用所有可用的系統資源以有效的方式。這使得很多有意義,因為大部分硬件有不止一個甚至多個CPU核心。如果一切都只有一個 Thread 執行,不可能完全使用所提供的資源。為了解決這個問題,許多應用程序執行多個 Thread 的運行代碼。在早期的 Java,這樣做是通過簡單地按需創建新 Thread 時,并行工作需要做。
但很快就發現,這不是完美的,因為創建 Thread 和回收會給他們帶來的開銷。在 Java 5 中,我們終于有了所謂的線程池,經常緩存 Thread,用來消除創建和回收 Thread 的開銷。這些池由 Executor 接口提供。Java 5 提供了許多有用的實現,在其內部發生顯著的變化,但思想都一脈相承的。創建 Thread 和重用他們提交一個任務時執行。這可以幫助創建和回收線程的開銷降到最低。
下圖顯示使用一個線程池執行一個任務,提交一個任務后會使用線程池中空閑的線程來執行,完成任務后釋放線程并將線程重新放回線程池:
[](https://github.com/waylau/essential-netty-in-action/blob/master/images/Figure%2015.1%20Executor%20execution%20logic.jpg)
1. Runnable 表示要執行的任務。這可能是任何東西,從一個數據庫調用文件系統清理。
2. 之前 runnable 移交到線程池。
3. 閑置的線程被用來執行任務。當一個線程運行結束之后,它將回到閑置線程的列表新任務需要運行時被重用。
4. 線程執行任務
Figure 15.1 Executor execution logic
這個修復 Thread 創建和回收的開銷,不需要每個新任務創建和銷毀新的 Thread 。
但使用多個 Thread 提供了資源和管理成本,作為一個副作用,引入了太多的上下文切換。這種會隨著運行的線程的數量和任務執行的數量的增加而惡化。盡管使用多個線程在開始時似乎不是一個問題,但一旦你把真正工作負載放在系統上,可以會遭受到重擊。
除了這些技術的限制和問題,其他問題可能發生在相關的維護應用程序/框架在未來或在項目的生命周期里。有效地說,增加應用程序的復雜性取決于對比。當狀態簡單時,寫一個多線程應用程序是一個辛苦的工作!你能解決這個問題嗎?在實際的場景中需要多個 Thread 規模;這是一個事實。讓我們看看 Netty 是解決這個問題。
- Introduction
- 開始
- Netty-異步和數據驅動
- Netty 介紹
- 構成部分
- 關于本書
- 第一個 Netty 應用
- 設置開發環境
- Netty 客戶端/服務端 總覽
- 寫一個 echo 服務器
- 寫一個 echo 客戶端
- 編譯和運行 Echo 服務器和客戶端
- 總結
- Netty 總覽
- Netty 快速入門
- Channel, Event 和 I/O
- 什么是 Bootstrapping 為什么要用
- ChannelHandler 和 ChannelPipeline
- 近距離觀察 ChannelHandler
- 總結
- 核心功能
- Transport(傳輸)
- 案例研究:Transport 的遷移
- Transport API
- 包含的 Transport
- Transport 使用情況
- 總結
- Buffer(緩沖)
- Buffer API
- ByteBuf - 字節數據的容器
- 字節級別的操作
- ByteBufHolder
- ByteBuf 分配
- 總結
- ChannelHandler 和 ChannelPipeline
- ChannelHandler 家族
- ChannelPipeline
- ChannelHandlerContext
- 總結
- Codec 框架
- 什么是 Codec
- Decoder(解碼器)
- Encoder(編碼器)
- 抽象 Codec(編解碼器)類
- 總結
- 提供了的 ChannelHandler 和 Codec
- 使用 SSL/TLS 加密 Netty 程序
- 構建 Netty HTTP/HTTPS 應用
- 空閑連接以及超時
- 解碼分隔符和基于長度的協議
- 編寫大型數據
- 序列化數據
- 總結
- Bootstrap 類型
- 引導客戶端和無連接協議
- 引導服務器
- 從 Channel 引導客戶端
- 在一個引導中添加多個 ChannelHandler
- 使用Netty 的 ChannelOption 和屬性
- 關閉之前已經引導的客戶端或服務器
- 總結
- 引導
- Bootstrap 類型
- 引導客戶端和無連接協議
- 引導服務器
- 從 Channel 引導客戶端
- 在一個引導中添加多個 ChannelHandler
- 使用Netty 的 ChannelOption 和屬性
- 關閉之前已經引導的客戶端或服務器
- 總結
- NETTY BY EXAMPLE
- 單元測試
- 總覽
- 測試 ChannelHandler
- 測試異常處理
- 總結
- WebSocket
- WebSocket 程序示例
- 添加 WebSocket 支持
- 測試程序
- 總結
- SPDY
- SPDY 背景
- 示例程序
- 實現
- 啟動 SpdyServer 并測試
- 總結
- 通過 UDP 廣播事件
- UDP 基礎
- UDP 廣播
- UDP 示例
- EventLog 的 POJO
- 寫廣播器
- 寫監視器
- 運行 LogEventBroadcaster 和 LogEventMonitor
- 總結
- 高級主題
- 實現自定義的編解碼器
- 編解碼器的范圍
- 實現 Memcached 編解碼器
- 了解 Memcached 二進制協議
- Netty 編碼器和解碼器
- 測試編解碼器
- EventLoop 和線程模型
- 線程模型的總覽
- EventLoop
- EventLoop
- I/O EventLoop/Thread 分配細節
- 總結
- 用例1:Droplr Firebase 和 Urban Airship
- 用例2:Facebook 和 Twitter