传统的bio线程模型是
用户发起请求,accept得到一个socket,然后从业务线程池取出一个线程去处理该用户的请求
业务线程池线程数 + acceptCount = 最大用户连接数
业务线程池线程数 = 最大并发处理请求数
调大acceptCount可以提高最大连接数
如果希望减少线程切换的消耗且连接数不变,则应该降低线程池数,提高acceptCount
nio一般有三个线程池
创建连接线程池
非阻塞io线程池
业务线程池
最大连接数与业务线程池线程数无关,完全在于配置
业务线程池线程数=最大并发处理请求数
可见线程模型并非是nio的优势。bio和nio最终其实都是一个用户对应一个线程的。
netty nio零拷贝是java应用层的零拷贝
https://stackoverflow.com/questions/20727615/is-nettys-zero-copy-different-from-os-level-zero-copy
另外提一下,socketChannel的write方法,由于系统层面要求内存地址是固定的,而java内的byte[]是特殊的对象,gc后内存地址很可能改变,因此必须使用堆外内存。所以对于web应用,因为往往都是先转换成java内部的byte[]对象,所以必然至少要经历一次往堆外内存的拷贝。
可见,线程模型和内存拷贝方面,nio并不比bio有优势。
个人认为,web中nio的优势还是在于,可以通过单线程完成多个通道的读写。比如在一个http服务器中,我们通过非阻塞的读,直到读完一个完整的http报文(或header),才下发到工作线程,由servlet去处理。