一個故事講清楚 NIO
- 一:BIO方式
- 二:NIO方式
- 三:非同步方式
- 四:小結
- 《Netty 實現原理與源碼解析 —— 精品合集》
- 《Spring 實現原理與源碼解析 —— 精品合集》
- 《MyBatis 實現原理與源碼解析 —— 精品合集》
- 《Spring MVC 實現原理與源碼解析 —— 精品合集》
- 《Spring Boot 實現原理與源碼解析 —— 精品合集》
- 《資料庫實體設計合集》
- 《Java 面試題 —— 精品合集》
- 《Java 學習指南 —— 精品合集》
假設某銀行只有10個職員。該銀行的業務流程分為以下4個步驟:
1) 顧客填申請表(5分鐘);
2) 職員審核(1分鐘);
3) 職員叫保安去金庫取錢(3分鐘);
4) 職員列印票據,並將錢和票據返回給顧客(1分鐘)。
我們看看銀行不同的工作方式對其工作效率到底有何影響。
一:BIO方式
每來一個顧客,馬上由一位職員來接待處理,並且這個職員需要負責以上4個完整流程。當超過10個顧客時,剩餘的顧客需要排隊等候。
我們算算這個銀行一個小時到底能處理多少顧客?一個職員處理一個顧客需要10分鐘(5+1+3+1)時間,一個小時(60分鐘)能處理6個顧客,一共10個職員,那就是隻能處理60個顧客。
可以看到銀行職員的工作狀態並不飽和,比如在第1步,其實是處於等待中。
這種工作其實就是BIO,每次來一個請求(顧客),就分配到線程池中由一個線程(職員)處理,如果超出了線程池的最大上限(10個),就扔到隊列等待 。
二:NIO方式
如何提高銀行的吞吐量呢?
思路:分而治之,將任務拆分開來,由專門的人負責專門的任務。
具體來講,銀行專門指派一名職員A,A的工作就是每當有顧客到銀行,他就遞上表格讓顧客填寫,每當有顧客填好表後,A就將其隨機指派給剩餘的9名職員完成後續步驟。
我們計算下這種工作方式下銀行一個小時到底能處理多少顧客?
假設顧客非常多,職員A的工作處於飽和中,他不斷的將填好表的顧客帶到櫃檯處理,櫃檯一個職員5分鐘能處理完一個顧客,一個小時9名職員能處理:9*(60/5)=108。
可見工作方式的轉變能帶來效率的極大提升。
這種工作方式其實就NIO的思路。下圖是非常經典的NIO說明圖,mainReactor線程負責監聽server socket,accept新連接,並將建立的socket分派給subReactor;subReactor可以是一個線程,也可以是線程池(一般可以設置為CPU核數),負責多路分離已連接的socket,讀寫網路數據,這裡的讀寫網路數據可類比顧客填表這一耗時動作,對具體的業務處理功能,其扔給worker線程池完成。
可以看到典型NIO有三類線程,分別是mainReactor線程、subReactor線程、work線程。不同的線程幹專業的事情,最終每個線程都沒空著,系統的吞吐量自然就上去了。