java之BIO与NIO图解
java中网络通信是通过Socket实现的,Socket分为ServerSocket与Socket两类;ServerSocket用于服务端,可以通过accept监听请求,监听到请求后返回Socket,用于具体完成数据传输,而客户端直接使用Socket发起请求并传输数据。
仍然存在的缺点:
1.每个Socket接收到,都会创建一个线程,线程的竞争、切换上下文影响性能;
2.每个线程都会占用栈空间和CPU资源;
3.并不是每个socket都进行IO操作,无意义的线程处理;
从JDK1.4开始,java增加了新的io模式的nio,nio在底层采用了新的处理方式,极大的提高了IO的效率,而Socket也属于io的一种,nio提供了相应的工具:ServerSocketChannel和SocketChannel,与原来的相对应;
总结一下NioSocket服务端的处理过程:
1.创建ServerSocketChannel并设置相应参数;
2.创建Selector并注册到ServerSocketChannel上;
3.调用Selector的select方法等待请求;
4.Selector接收到请求后使用selectKeys返回SelectKey的集合;
5.使用SelecttionKey获取到Channel、Selctor和操作类型并进行具体操作;
优化:
一银行办理业务的升级为例:
1.单窗口办理业务-->多窗口办理业务;
2.客户排队模式-->银行取号机登记注册式(取到号后可以去干其他事情,听到叫号再去办理)
3.告诉业务员一项业务,办理一项-->一次性提交资料与信息,全部一次办理(如果是复杂业务,则交给后台其他业务员办理,当前业务员继续处理该窗口负责业务);
以下就是NIO的具体优化(与上面场景可对应)
1.Selector通过其静态工厂方法open创建后注册到静态工厂方法创建的ServerSocketChannel上,降低了连接开闭资源的消耗(NIO多路复用);
2.操作分离的请求处理,避免了原accept后操作的阻塞;
3.Buffer的使用降低了原生read/write的阻塞;
其中用到了Buffer,在此简介一下:
Buffer是java.nio的一个类,其有4个属性非常重要:
capacity :容量,最多可以保存元素的数量,创建时设置,过程中不可变;
limit: 可以使用的上限,里面有多少数据,上限就是多少;
position: 当前操作元素所在的索引位置,开始为0,随着get与put方法自动更新;
mark: 用来暂时保存postion的位置,可以暂时操作其他元素,然后通过reset将mark值恢复到postion,即Buffer.reset();
buffer.clear:重新初始化,limit=capacity,position=0,mark=-1;
buffer.flip():buffer每保存一个数据,position+1,保存完成后将最后的postion赋值给limit,然后恢复到0,这样就可以读取数据了(数据锁定);