NIO,一种基于通道和缓冲区的I/O方式,可以使用native函数库直接分配堆外内存,然后通过一个存储在java

堆的DirectBteBuffer对象作为这块内存的引用进行操作,避免了再java堆和native堆中来回复制数据。

NIO是一种同步非阻塞的IO模型。同步是指线程不断轮询IO事件是否就绪,非阻塞指线程在等待IO的时候,可以

同时做其他任务。同步的核心是Selector,Selector代替了线程本身轮询IO事件,避免了阻塞同时减少了不必要的

线程消耗;非阻塞的核心就是通道和缓冲区,当IO事件就绪时,可以通过写道缓冲区,保证IO的成功,而无需线程

阻塞式地等待。

Buffer

为什么NIO是基于缓冲区的IO方式,因为当一个连接建立完成后,IO数据未必会马上到达,为了当数据达到时能够正确

完成IO操作,在BIO(阻塞IO)中,等待IO的线程必须被阻塞,以全天候地进行IO操作。为了解决这种IO方式的低效问题,

引入了缓冲区的概念,当数据达到时,可以预先被写入缓冲区,再由缓冲区交给线程,因此线程无需阻塞等待IO

通道

当执行:SocketChannel.write(Buffer),将一个buffer写到一个通道中。通道来说相对比较抽象。通道是I/O传输发生时通过的入口

而缓冲区是这些数据传输的来源或目标。对于离开缓冲区的传输,你想传递出去的数据被置于一个缓冲区,被传送到通道。对于

传回缓冲区的传输,一个通道将数据放置于你所提供的缓冲区中。

例如有个服务器通道ServerSocketChannel serverChannel,一个客户端通道SocketChannel clientChannel;服务器缓存区

serverBuffer,客户端缓冲区clientBuffer。当服务器想向客户端发送数据时,需要调用clientChannel.write(serverBuffer)。当

客户端要读时,调用clientChannel.read(clientBuffer);当客户端向服务器发送数据时,需要调用serverChannel.write(clientBuffer)

当服务器要读时,调用serverChannel.read(serverBuffer); 可以理解为在NIO中,如果想将data发送到目标端,则需要将存储该

data的buffer,写入到目标端channel中,然后再从channel中读取数据到目标端的buffer中。

Selector

通道和缓冲区的机制,使得现场无需阻塞等待IO事件的就绪,但总的要有人来监管这些IO事件。 这就由selector来完成。selector允许

单个现场处理多个channel,如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用selector就比较方便

要使用selector,的向selector注册channel,然后调用它的select方法,这个方法会一直阻塞到某个注册的通道有事件就绪,这就是轮询。

一旦这个方法返回,线程就可以处理这些事件。

selector中注册的感兴趣事件有: OP_ACCEPT  OP_CONNECT  OP_READ  OP_WRITE

简单基于NIO方式实现server/client示例

package com.exe.learn.demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator; public class ServerNio { private Selector selector; public void initServer(int port) throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
//设置非阻塞模式
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(port));
this.selector = Selector.open();
//将selector注册到服务端
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} public void listen() throws IOException {
System.out.println("服务端启动》》》》》");
while(true) {
selector.select();
Iterator<SelectionKey> ite = this.selector.selectedKeys().iterator();
while(ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
ite.remove();
if(key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = server.accept();
socketChannel.configureBlocking(false);
socketChannel.write(ByteBuffer.wrap(new String("来自服务端的信息").getBytes()));
socketChannel.register(this.selector, SelectionKey.OP_READ);
}else if(key.isReadable()){
readFromClient(key);
}
}
}
} private void readFromClient(SelectionKey key) throws IOException {
SocketChannel server = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(10);
server.read(buffer);
byte[] data = buffer.array();
String msg = new String(data).trim();
System.out.println("来自客户端的信息" + msg);
server.write(ByteBuffer.wrap(new String(msg).getBytes()));
} public static void main(String[] args) throws IOException {
ServerNio server = new ServerNio();
server.initServer(1024);
server.listen();
}
}
package com.exe.learn.demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator; public class ClientNio { private Selector selector; public void initClient(String ip, int port) throws IOException {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
this.selector = Selector.open();
//连接server端
socketChannel.connect(new InetSocketAddress(ip, port));
socketChannel.register(selector, SelectionKey.OP_CONNECT);
} public void listen() throws IOException {
System.out.println("客户端启动》》》》》》");
while(true) {
selector.select();
Iterator<SelectionKey> ite = this.selector.selectedKeys().iterator();
while(ite.hasNext()) {
SelectionKey key = ite.next();
ite.remove();
if(key.isConnectable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
if(socketChannel.isConnectionPending()) {
socketChannel.finishConnect();
}
socketChannel.configureBlocking(false);
socketChannel.write(ByteBuffer.wrap(new String("向服务器发送信息了".getBytes(), "UTF-8").getBytes()));
socketChannel.register(selector, SelectionKey.OP_READ);
}else if(key.isReadable()) {
readFromServer(key);
}
}
}
} private void readFromServer(SelectionKey key) throws IOException {
SocketChannel server = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(10);
server.read(buffer);
byte[] data = buffer.array();
String msg = new String(data).trim();
System.out.println("来自服务端的信息" + msg);
server.write(ByteBuffer.wrap(new String(msg).getBytes()));
} public static void main(String[] args) throws IOException {
ClientNio client = new ClientNio();
client.initClient("127.0.0.1", 1024);
client.listen();
}
}

NIO摘录的更多相关文章

  1. NIO知识摘录

    在 JDK 1. 4 中 新 加入 了 NIO( New Input/ Output) 类, 引入了一种基于通道和缓冲区的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个 ...

  2. NIO学习笔记

    零.前言 这里整理摘录了我了解NIO的一些笔记. 参考资料: 1.深入浅出NIO之Channel.Buffer 2.深入浅出NIO之Selector实现原理 3.Java NIO vs. IO 一.N ...

  3. 转载 IO、文件、NIO【草案四】

    本章目录: 1.IO类相关内容 2.文件和目录 3.文件高级操作  NIO详解[1]——缓冲区(Buffer)[深入理解,总结自<Java-NIO>]: [*:下边的Buffer又指代抽象 ...

  4. tcp nio 远程主机强迫关闭了一个现有的连接

    import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import ...

  5. 源码分析netty服务器创建过程vs java nio服务器创建

    1.Java NIO服务端创建 首先,我们通过一个时序图来看下如何创建一个NIO服务端并启动监听,接收多个客户端的连接,进行消息的异步读写. 示例代码(参考文献[2]): import java.io ...

  6. BIO\NIO\AIO记录

    IO操作可以分为3类:同步阻塞(BIO).同步非阻塞(NIO).异步(AIO). 同步阻塞(BIO):在此种方式下,用户线程发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后, ...

  7. MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录

    注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...

  8. 支撑Java NIO 与 NodeJS的底层技术

    支撑Java NIO 与 NodeJS的底层技术 众所周知在近几个版本的Java中增加了一些对Java NIO.NIO2的支持,与此同时NodeJS技术栈中最为人称道的优势之一就是其高性能IO,那么我 ...

  9. Java I/O and NIO [reproduced]

    Java I/O and NIO.2---Five ways to maximize Java NIO and NIO.2---Build more responsive Java applicati ...

随机推荐

  1. myeclipse web project 名字可以包含中文吗?

    1.理论上是可以有中文名的,但是由于中文因为编码的原因导致不可预料的后果,所以一般不建议使用中文名称 2.   Myeclipse中修改Web项目名字的方法 方法一:新建项目法(有效的备份原来的项目) ...

  2. tensorflow2 矩阵乘法问题

    tensorflow2再做矩阵相乘的时候如果维度有None,则矩阵相乘结果不对. 也不知道为什么,只能用矩阵对应元素相乘在相加的形式来实现矩阵相乘,这个困扰了我好几天,所以记下来. inputs_ti ...

  3. Fiddler抓包工具-拦截,断点

    1.拦截网页 先拦截请求-F11设置拦截 -F12抓包 2.修改金额 宽带 下行:100M上行:8M 一般家用的都是下行高,企业用都是上下行对等.企业要搭建网站就需要上行. 我们去访问网站,服务器根据 ...

  4. P1970花匠

    传送 首先,这道题据说是一个dp 其次,贪心就能做 我们先来看好想好写的贪心 按照题目来,所有偶数点要么都是凸的,要么都是凹的,不能有凸有凹.我们把每株花的高度都在平面直角坐标系中点出来,再连线.这样 ...

  5. day31—CSS Reset 与页面居中布局

    转行学开发,代码100天——2018-04-16 报名的网易前端开发课程今天正式开课了,这也是毕业后首次付费进行的正式培训课程学习.以此,记录每天学习内容. 今天学了两个方面的知识: 1. CSS   ...

  6. delphi中的idhttpserver如何才能收到idhttp发送来的exe\rar文件呢

    http://zhidao.baidu.com/link?url=-q2oXqYCKBZ9OgFDEHAcQwQEY_NroHcqGvVfKW67X5sF9LdjAAB_HPXQo04VxStFVS7 ...

  7. java 虚方法。 后面new 那个类, 就调用哪个类的方法 ,而非定义类的方案。 关于父子 类的 呵呵

    java   虚方法.     后面new  那个类, 就调用哪个类的方法 ,而非定义类的方案.  关于父子 类的   呵呵 在多态的情况下,声明为父类类型的引用变量只能调用父类中的方法,但如果此变量 ...

  8. Delphi保存网页中的图片

    WEBBrowser已经打开了URL     V     =   WEBBrowser.Document.body.createControlRange();     V1   =   WEBBrow ...

  9. CentOS7 - 安装 VirtualBox

    参考资料 最新的可用安装包可以从这里下载 VirtualBox 是 x86 硬件虚拟化产品,功能上与 VMware Server.KVM.及 Xen 类似,但是 VirtualBox 不修改 Linu ...

  10. 微信小程序这一块(续)

    1.设置头部的信息 通过wx.setNavigationBarTitle 详情见:https://developers.weixin.qq.com/miniprogram/dev/api/ui/nav ...