java nio 理解_JAVA NIO 的理解学习

java nio 基于事件机制监听 不同的channel 的动作从而做出相应的响应。响应线程无需像传统io阻塞等待响应。主要涉及到的是 Buffer,Channel 以及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 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();

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值