javaNio 学习笔记(一)

javaNio 学习笔记(一)

学习参考文档:

http://tutorials.jenkov.com/java-nio/index.html

什么是javaNio

java Nio是java new IO。是java1.4新增的API。它提供了另一种不同于标准IO的实现方式来实现IO

知其然知其所以然

为什么要使用java Nio?

弄懂了为什么要使用Java NIO也就是知道我们为啥要学NIO了。

首先NIO出现就是提供了替代标准IO的一种IO实现方式。那么为什么要替换标准IO呢?

我们来看下下面的例子:

// server
public class Bio {
    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(2999);
            System.out.println("server 监听2999端口等待客户端连接" + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());
            Socket socket = server.accept();
            System.out.println("server 监听2999端口等待客户端接受数据" + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());
            // 从套接字中获取输入流
            InputStream inputStream = socket.getInputStream();
            byte[] bytes = new byte[1024];
            inputStream.read(bytes);
            System.out.println("get message from client: " + new String(bytes) + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());

            inputStream.close();
            socket.close();
            server.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// client
public class Client {

    public static void main(String[] args) {

        try {
            // 建立连接
            System.out.println("客户端准备连接服务器 2999端口" + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());
            Socket socket = new Socket("127.0.0.1", 2999);
            System.out.println("客户端连接服务器 2999端口" + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());
            // 向socket写入数据
            OutputStream outputStream = socket.getOutputStream();
            System.out.println("客户端连接服务器开始写入数据" + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());
            socket.getOutputStream().write("hi, be happy".getBytes("UTF-8"));
            System.out.println("客户端连接服务器开始写入完成" + Instant.now().atOffset(ZoneOffset.ofHours(8)).toInstant());
            outputStream.close();
            socket.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}

先启动server,然后在启动client(为了让结果比较清晰建议打断点运行),返回结果如下

// server 返回结果:
server 监听2999端口等待客户端连接2020-06-11T14:35:58.428Z
server 监听2999端口等待客户端接受数据2020-06-11T14:36:16.120Z
get message from client: hi, be happy

// client 返回结果    
客户端准备连接服务器 2999端口2020-06-11T14:36:02.026Z
客户端连接服务器 2999端口2020-06-11T14:36:35.664Z
客户端连接服务器开始写入数据2020-06-11T14:36:40.984Z
客户端连接服务器开始写入完成2020-06-11T14:36:42.969Z    

运行断点的时候会发现,当server执行到server.accept()inputStream.read()的时候程序会阻塞,让程序等待,这样会影响执行效率。这也就是为什么会有NIO来替代IO。

先自己思考解决方案

如果是让我来解决这个问题,该如何处理呢?

可以开线程,每一个线程来处理一个client的连接。这样即使阻塞也是只阻塞当前线程。这样即使阻塞也只是阻塞当前线程,而不会对其他线程造成影响。当然这么做就会消耗系统资源,因为线程是有限的,我们不可能无限的开启线程,若客户端一直未连接就需要做超时处理,将线程关闭。

Java NIO是如何来做的?

这个问题可能需要等到学习完java NIO之后才可能回答的出来。那么下面我就开始学习Java NIO。

java NIO简单导读

参考上面文档地址

  • 传统IO是面向流的,而java NIO则是面向channelsbuffers的。数据都是从channel中读取到buffer或者从channel中写入buffer
  • java NIO是非阻塞IO,即不会产生上面的问题。线程可以让channel(有的人叫通道)去读取buffer中的数据,这个时候线程可以做其他事情。当数据程从channel读取到buffer的时候线程在继续处理这部分事情。对于写也是一样。
  • Java NIO还提供了一个selectorselector是一个对象,可以监控多个通道的事件(如:连接打开,数据到达等)。这样可以让单个线程监视多个channel

java NIO 基本概念

java NIO主要的核心组件如下:

  • Channels(通道、管道、频道)
  • buffers(数据缓冲区)
  • Selector(选择器,从导读的概念来看感觉有点想监听器)

当然java NIO还有一些其他组件,后面我会慢慢进行学习。

channelbuffer就可以理解潮汐车道俩头的地点。数据可以从频道(channel)中写入缓冲区(buffer).

也可以从缓冲区读取到频道中。

主要实现的管道类型

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

核心的缓冲区

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

选择器

选择器的作用就是能让单个线程来处理多线程的事情。要使用选择器,需要注册频道。然后调用它的select()方法。此方法将阻塞,直到为其中一个已注册通道准备好事件为止。方法返回后,线程就可以处理这些事件。(有传入的连接,接收到的数据等等)

这些类型后续学习中我会进行联系并尽量做详细了解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值