傳統(tǒng)的bio線程模型是
用戶發(fā)起請求,accept得到一個socket,然后從業(yè)務(wù)線程池取出一個線程去處理該用戶的請求
業(yè)務(wù)線程池線程數(shù) + acceptCount = 最大用戶連接數(shù)
業(yè)務(wù)線程池線程數(shù) = 最大并發(fā)處理請求數(shù)
調(diào)大acceptCount可以提高最大連接數(shù)
如果希望減少線程切換的消耗且連接數(shù)不變,則應(yīng)該降低線程池數(shù),提高acceptCount
nio一般有三個線程池
創(chuàng)建連接線程池
非阻塞io線程池
業(yè)務(wù)線程池
最大連接數(shù)與業(yè)務(wù)線程池線程數(shù)無關(guān),完全在于配置
業(yè)務(wù)線程池線程數(shù)=最大并發(fā)處理請求數(shù)
可見線程模型并非是nio的優(yōu)勢。bio和nio最終其實都是一個用戶對應(yīng)一個線程的。
netty nio零拷貝是java應(yīng)用層的零拷貝
https://stackoverflow.com/questions/20727615/is-nettys-zero-copy-different-from-os-level-zero-copy
另外提一下,socketChannel的write方法,由于系統(tǒng)層面要求內(nèi)存地址是固定的,而java內(nèi)的byte[]是特殊的對象,gc后內(nèi)存地址很可能改變,因此必須使用堆外內(nèi)存。所以對于web應(yīng)用,因為往往都是先轉(zhuǎn)換成java內(nèi)部的byte[]對象,所以必然至少要經(jīng)歷一次往堆外內(nèi)存的拷貝。
可見,線程模型和內(nèi)存拷貝方面,nio并不比bio有優(yōu)勢。
個人認為,web中nio的優(yōu)勢還是在于,可以通過單線程完成多個通道的讀寫。比如在一個http服務(wù)器中,我們通過非阻塞的讀,直到讀完一個完整的http報文(或header),才下發(fā)到工作線程,由servlet去處理。