这几天堵了java nio这本书,偶遇iteye上文章,转之:http://weixiaolu.iteye.com/blog/1479656
Java NIO原理图文分析及代码实现
如果你细细分析,一定会发现阻塞I/O存在一些缺点。根据阻塞I/O通信模型,我总结了它的两点缺点:
(注:每个线程的处理流程大概都是读取数据、解码、计算处理、编码、发送响应。)
服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件。我们以服务端为例,如果服务端的通道上注册了读事件,某时刻客户端给服务端发送了一些数据,阻塞I/O这时会调用read()方法阻塞地读取数据,而NIO的服务端会在selector中添加一个读事件。服务端的处理线程会轮询地访问selector,如果访问selector时发现有感兴趣的事件到达,则处理这些事件,如果没有感兴趣的事件到达,则处理线程会一直阻塞直到感兴趣的事件到达为止。下面是我理解的java NIO的通信模型示意图:
二.java NIO服务端和客户端代码实现
package cn.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;/** * NIO服务端 * @author 小路 */public class NIOServer {//通道管理器private Selector selector;/** * 获得一个ServerSocket通道,并对该通道做一些初始化的工作 * @param port 绑定的端口号 * @throws IOException */public void initServer(int port) throws IOException {// 获得一个ServerSocket通道ServerSocketChannel serverChannel = ServerSocketChannel.open();// 设置通道为非阻塞serverChannel.configureBlocking(false);// 将该通道对应的ServerSocket绑定到port端口serverChannel.socket().bind(new InetSocketAddress(port));// 获得一个通道管理器this.selector = Selector.open();//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,//当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。serverChannel.register(selector, SelectionKey.OP_ACCEPT);}/** * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 * @throws IOException */@SuppressWarnings("unchecked")public void listen() throws IOException {System.out.println("服务端启动成功!");// 轮询访问selectorwhile (true) {//当注册的事件到达时,方法返回;否则,该方法会一直阻塞selector.select();// 获得selector中选中的项的迭代器,选中的项为注册的事件Iterator ite = this.selector.selectedKeys().iterator();while (ite.hasNext()) {SelectionKey key = (SelectionKey) ite.next();// 删除已选的key,以防重复处理ite.remove();// 客户端请求连接事件if (key.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) key.channel();// 获得和客户端连接的通道SocketChannel channel = server.accept();// 设置成非阻塞channel.configureBlocking(false);//在这里可以给客户端发送信息哦channel.write(ByteBuffer.wrap(new String("向客户端发送了一条信息").getBytes()));//在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。channel.register(this.selector, SelectionKey.OP_READ);// 获得了可读的事件} else if (key.isReadable()) {read(key);}}}}/** * 处理读取客户端发来的信息 的事件 * @param key * @throws IOException */public void read(SelectionKey key) throws IOException{// 服务器可读取消息:得到事件发生的Socket通道SocketChannel channel = (SocketChannel) key.channel();// 创建读取的缓冲区ByteBuffer buffer = ByteBuffer.allocate(10);channel.read(buffer);byte[] data = buffer.array();String msg = new String(data).trim();System.out.println("服务端收到信息:"+msg);ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());channel.write(outBuffer);// 将消息回送给客户端}/** * 启动服务端测试 * @throws IOException */public static void main(String[] args) throws IOException {NIOServer server = new NIOServer();server.initServer(8000);server.listen();}}
客户端:
/** * */package cn.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;/** * NIO客户端 * @author 小路 */public class NIOClient {//通道管理器private Selector selector;/** * 获得一个Socket通道,并对该通道做一些初始化的工作 * @param ip 连接的服务器的ip * @param port 连接的服务器的端口号 * @throws IOException */public void initClient(String ip,int port) throws IOException {// 获得一个Socket通道SocketChannel channel = SocketChannel.open();// 设置通道为非阻塞channel.configureBlocking(false);// 获得一个通道管理器this.selector = Selector.open();// 客户端连接服务器,其实方法执行并没有实现连接,需要在listen()方法中调//用channel.finishConnect();才能完成连接channel.connect(new InetSocketAddress(ip,port));//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT事件,注册该事件后,//当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。channel.register(selector, SelectionKey.OP_CONNECT);}/** * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 * @throws IOException */@SuppressWarnings("unchecked")public void listen() throws IOException {// 轮询访问selectorwhile (true) {// 选择一组可以进行I/O操作的事件,放在selector中,该方法会阻塞selector.select();// 获得selector中选中的项的迭代器Iterator ite = this.selector.selectedKeys().iterator();while (ite.hasNext()) {SelectionKey key = (SelectionKey) ite.next();// 删除已选的key,以防重复处理ite.remove();// 连接事件发生if (key.isConnectable()) {SocketChannel channel = (SocketChannel) key.channel();// 如果正在连接,则完成连接if(channel.isConnectionPending()){channel.finishConnect();}// 设置成非阻塞channel.configureBlocking(false);//在这里可以给服务端发送信息哦channel.write(ByteBuffer.wrap(new String("向服务端发送了一条信息").getBytes()));//在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。channel.register(this.selector, SelectionKey.OP_READ);// 获得了可读的事件} else if (key.isReadable()) {read(key);}}}}/** * 处理读取服务端发来的信息 的事件 * @param key * @throws IOException */public void read(SelectionKey key) throws IOException{//和服务端的read方法一样}/** * 启动客户端测试 * @throws IOException */public static void main(String[] args) throws IOException {NIOClient client = new NIOClient();client.initClient("localhost",8000);client.listen();}}
小结:
个人补充:java nio主要是三个大的方面。 buffer(bytebuffer,longbuffer,shortbuffer等等,注意stringbuffer不是nio的,是java.lang包里面的) channel主要是filechannel和socketchannel两大类。channel是双向的,但是对于file是有读写权限的,所以使用channel的时候要加以判断 channel和file是可以实现map机制的文件内存映射的,这个是高速的io,比普通的文件io读取要快得多。(代码书上有,我不写了) selector这个是最神奇的。channel的server和client都要注册的selector上面。有selector轮训那个已经读满了。书上举例的银行出纳员的例子。感觉还是挺贴切的。selector这个东西让人不由得想起了大话设计模式中的观察者模式,中枪啊!注册时间,到时通知。。
jdk1.4还带来了Character和正则方面的东西,不是重点,带过。。 |
- 浏览: 958861 次
- 性别:
- 来自: 魔都
最新评论
-
lkjxshi:
你都这水平了还考这个证干嘛
SCJP 认证考试指南 -
钟逸华:
问的真多
百度java开发面试题(转) -
zuimeitulip:
觉得我就是这样的,从小阅读量就很少,导致现在的读的速度非常慢, ...
让读书成为一种习惯 -
DDT_123456:
我觉得你是不符合要求。问你hashmap的那个问题,你那样回答 ...
阿里面试2(转) -
jingjing0907:
刚刚写了很多读过此博客的感受,竟然没有发上去,以为我注册账号还 ...
让读书成为一种习惯
相关推荐
java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...
Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于替代标准I/O(BIO)模型的一种新机制。NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据...
Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...
### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...
Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(IO)相比,提供了更加高效的数据传输方式。在Java NIO中,"新"主要体现在非阻塞和多路复用这两个特性上,这使得NIO更适合于...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,它为Java应用程序提供了更高效的数据传输方式。传统的Java I/O模型(BIO)在处理大量并发连接时效率较...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在传统的Java IO模型中,读写操作是阻塞的,即当调用read或write方法时,线程会等待数据准备好或...
java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...
Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的 Blocking I/O(同步阻塞I/O)相对。NIO在Java 1.4版本引入,其设计目标是提供一种更高效、更灵活的I/O操作方式,特别适合处理大量并发连接...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,它为Java应用程序提供了更高效、灵活的I/O操作方式。NIO与传统的 Blocking I/O(阻塞I/O)模式相比,...
### Java NIO 实现Socket通信详解 #### 一、NIO与传统IO的区别及优势 在探讨如何使用Java NIO实现Socket通信之前,我们需要先理解NIO(Non-blocking I/O,非阻塞I/O)与传统阻塞I/O之间的区别。 **传统阻塞I/O...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在Java 1.4版本中引入,NIO提供了一种全新的I/O编程方式,使得Java开发者能够更高效地处理I/O操作...