JAVA NIO 的理解学习
2016-08-16 00:00
309 查看
java nio 基于事件机制监听 不同的channel 的动作从而做出相应的响应。响应线程无需像传统io阻塞等待响应。主要涉及到的是 Buffer,Channel 以及Selector
其中 Buffer 是缓冲器,数据的读写都必须从channel 经过buffer 获取或者写入channel中。
Channel 基于Nio 必须是无阻塞的 每一个客户端和服务端连接都回在服务端新建一个socketChannel,并通过 channel.register(selector,eventKey) 注册到Selector.selector 可以单线程 阻塞监听是否有事件发生,如果存在 调用事件注册的 服务进行相应的处理。
核心在于Selector。
以下是写的测试类:
其中 Buffer 是缓冲器,数据的读写都必须从channel 经过buffer 获取或者写入channel中。
Channel 基于Nio 必须是无阻塞的 每一个客户端和服务端连接都回在服务端新建一个socketChannel,并通过 channel.register(selector,eventKey) 注册到Selector.selector 可以单线程 阻塞监听是否有事件发生,如果存在 调用事件注册的 服务进行相应的处理。
核心在于Selector。
以下是写的测试类:
package com.hrd.nio; import java.io.IOException; 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; import java.util.UUID; /** * 服务端和客户端 分别启动一个SelectorThread 用于监听事件,这里由于本机写成一个。 * @author hurd@omeng.cc * @version v0.1 * @date 2016/8/16 * @desc TODO * @see */ public class SelectThread extends Thread { private String threadName; private Selector selector; public SelectThread(String threadName, Selector selector){ this.threadName = threadName; this.selector = selector; } @Override public void run() { Thread.currentThread().setName(threadName); try { while(true){ //阻塞 selector.select(); //获取选择器中已经就绪的SelectionKey集合 Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); //遍历 while (iterator.hasNext()){ SelectionKey key = iterator.next(); //删除 iterator.remove(); //接受连接就绪事件 if(key.isAcceptable()){ ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = ssc.accept(); //套接字通道设置为非阻塞模式 socketChannel.configureBlocking(false); //向socket通道 注册读就绪事件 socketChannel.register(selector, SelectionKey.OP_READ); }else if(key.isReadable()){ //SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(100); ((SocketChannel)key.channel()).read(byteBuffer); //将写模式变为读模式 byteBuffer.flip(); //读取完毕 if(byteBuffer.limit()>0){ System.out.println("线程:"+Thread.currentThread().getName()+"消息:" + new String(byteBuffer.array()).trim()); } key.interestOps(key.interestOps() | SelectionKey.OP_WRITE); }else if(key.isWritable()){ //暂时还没想明白这个写就绪事件干嘛用的。。。 System.out.println("写就绪事件触发了,线程名:"+Thread.currentThread().getName()); ByteBuffer byteBuffer = ByteBuffer.allocate(1000); byteBuffer.put((Thread.currentThread().getName() + UUID.randomUUID().toString()).getBytes()); SocketChannel socketChannel = (SocketChannel) key.channel(); byteBuffer.flip(); socketChannel.write(byteBuffer); key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); }else if(key.isConnectable()){ SocketChannel socketChannel = (SocketChannel) key.channel(); //判断连接是否完成 int i =0; while(! socketChannel.finishConnect()){ if(++i>10){ throw new RuntimeException("socket连接超时"); } System.out.println("sock连接未完成,等待中...."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } //向socket通道 注册读就绪事件 socketChannel.register(selector, SelectionKey.OP_READ); ByteBuffer byteBuffer = ByteBuffer.allocate(100); byteBuffer.put((Thread.currentThread().getName()+"客户端完成连接啦,感谢服务端哈").getBytes()); byteBuffer.flip(); socketChannel.write(byteBuffer); } } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
package com.hrd.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; /** * @author hurd@omeng.cc * @version v0.1 * @date 2016/8/16 * @desc TODO * @see */ public class ServerSocketMain { public static void main(String[] args) throws IOException, InterruptedException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); //绑定 ip 地址 serverSocketChannel.bind(new InetSocketAddress(8888)); //注册感兴趣的事件 这里注册 注册accept 和读就绪事件 Selector selector = Selector.open(); SelectThread threadThread = new SelectThread("server side",selector); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //服务端阻塞监听selector 事件 threadThread.start(); serverSocketChannel.accept(); System.out.println("服务端socket 启动完成...."); // wait 主线程 后续的操作交给子线程处理 synchronized (Thread.currentThread()){ Thread.currentThread().wait(); } } }
package com.hrd.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; /** * @author hurd@omeng.cc * @version v0.1 * @date 2016/8/16 * @desc TODO * @see */ public class ClientSocketMain { public static void main(String[] args) throws IOException, InterruptedException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress(8888)); Selector selector = Selector.open(); SelectThread clientSelectThread = new SelectThread("client side:",selector); socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ); clientSelectThread.start(); System.out.println("客户端启动完成...."); synchronized (Thread.currentThread()){ Thread.currentThread().wait(); } } }
相关文章推荐
- 理解XForm——学习IBM DW的资料 (4)
- 学习C++(一) 我现在理解的C++
- 学习理解的过程
- 学习Shark的一些理解 (选择自 smilingleo 的 Blog)
- 关于正在学习的一个项目的理解(1)
- Windows的理解-开始学习Windows编程
- Mcad学习笔记之委托再理解(delegate的构造器,MulticastDelegate,BeginInvoke,EndInvoke,Invoke4个方法的探讨)
- 写给自己看的,理解J2EE,总结自己的学习
- 马牛的C#学习(第四天)-从windows应用程序理解OOP|定义类|构造函数的执行顺序
- portal学习(2)-理解 portal .portlet. portlert container
- 学习C++(一) 我现在理解的C++ 选择自 MatrixCpp 的 Blog
- Java学习过程应该深入理解的一些重点
- Spring学习笔记:1、概念理解
- Spring学习笔记:1、概念理解
- 模式学习的自我理解和疑惑(1)
- 理解XForm——学习IBM DW的资料
- 学习顺便翻译:理解jsp模式2架构——MVC设计模式探险
- 【转载】Java学习过程应该深入理解的一些重点
- 操作系统学习常见疑惑问与答[编码实践部分]—问题1:org指令深入理解
- 快速学习,理解.SQL注入技术