Java Nio 学习笔记

2012年12月11日记录

今日总结

今天主要主要花了半下午时间学习了Java Nio的内容,学习链接:
极客学院NIO教程,这篇也是翻译国外大神的,有一些错别字。
当然,有兴趣的同学可以看看原文:教程原文
作者还很好心的提供了一个利用NIO写的非阻塞服务器,地址也给出来:
https://github.com/jjenkov/java-nio-server

知识点

1,Nio是java 1.4 之后提供的非阻塞IO包
2,核心类:channels,butter,selectors
3,Pipe, 提供线程之间数据传输的通道
3,核心思想:
NIO是面向缓存区的,阻塞IO是直接面向流的
NIO优点:
1,可以大大减少线程数量,可以利用seletor在单线程里处理多个网络请求读写,提高并发量。
2,可以对缓存器中的数据做后续的处理
缺点:
数据的读取会相对复杂

代码

使用FileChannel读文件

RandomAccessFile aFile1 = new RandomAccessFile("README.md1", "rw");
FileChannel channel = aFile.getChannel();
// 强制写完就刷新
channel.force(true);
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
while (read != -1) {
        // 取数据
        byteBuffer.flip();
        // 是否含有内容
        if (byteBuffer.hasRemaining()) {
            System.out.println((new String(byteBuffer.array(), "utf-8")));
        }
        byteBuffer.clear(); // compact
        read = channel.read(byteBuffer);
    }

scatter gather 的概念

// scatter 一对多 gather 多对一
ByteBuffer byteBuffer1 = ByteBuffer.allocate(100);
ByteBuffer byteBuffer2 = ByteBuffer.allocate(100);
// read()方法内部会负责把数据按顺序写进传入的buffer数组内。一个buffer写满后,接着写到下一个buffer中
ByteBuffer[] byteBuffers = {byteBuffer1, byteBuffer2};
channel.read(byteBuffers);
// 如果buffer的容量是128字节,但它只包含了58字节数据,那么写入的时候只有58字节会真正写入
channel.write(byteBuffers);

selector 单线程注册多个channel

// selector 单线程管理多个channel
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
selectableChannel.configureBlocking(false);
SocketChannel socketChannel1 = SocketChannel.open();
selectableChannel1.configureBlocking(false);
// 注册关注集合 第二个参数代表关注的时间  connect accept read write 四种事件可关注
SelectionKey selectionKey = selectableChannel.register(selector, SelectionKey.OP_READ);
SelectionKey selectionKey1 = selectableChannel1.register(selector, SelectionKey.OP_READ);

selector 读取多个channel:

while(true) {
	int readyChannels = selector.select();
	if(readyChannels == 0) continue;
	Set<SelectionKey> selectedKeys = selector.selectedKeys();
	Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
	while(keyIterator.hasNext()) {
		 SelectionKey key = keyIterator.next();
		 if(key.isAcceptable()) {
		     // a connection was accepted by a ServerSocketChannel.
		 } else if (key.isConnectable()) {
		     // a connection was established with a remote server.
		 } else if (key.isReadable()) {
		     // a channel is ready for reading
		 } else if (key.isWritable()) {
		     // a channel is ready for writing
		 }
		 keyIterator.remove();
	}
}

创建ServerSocketChannel,等待client端连接

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
while (true) {
      SocketChannel socketChannel2 = serverSocketChannel.accept();
     //do something with socketChannel...
}

客户端连接

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
while (!socketChannel.finishConnect()) {
       //wait, or do something else...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值