龙空技术网

java Nio 初级学习

非鸽传书 115

前言:

如今兄弟们对“javanio与io”可能比较看重,咱们都想要分析一些“javanio与io”的相关内容。那么小编同时在网上网罗了一些有关“javanio与io””的相关资讯,希望小伙伴们能喜欢,姐妹们快快来学习一下吧!

javaNio 学习笔记(一)

学习参考文档:

什么是javaNio

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

知其然知其所以然

为什么要使用java Nio?

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

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

我们来看下下面的例子:

// serverpublic 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();        }    }}// clientpublic 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.428Zserver 监听2999端口等待客户端接受数据2020-06-11T14:36:16.120Zget 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中写入bufferjava NIO是非阻塞IO,即不会产生上面的问题。线程可以让channel(有的人叫通道)去读取buffer中的数据,这个时候线程可以做其他事情。当数据层从channel读取到buffer的时候线程在继续处理这部分事情。对于写也是一样。Java NIO还提供了一个selectorselector是一个对象,可以监控多个通道的事件(如:连接打开,数据到达等)。这样可以让单个线程监视多个channeljava NIO 基本概念

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

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

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

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

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

主要实现的管道类型

FileChannelDatagramChannelSocketChannelServerSocketChannel

核心的缓冲区

ByteBufferCharBufferDoubleBufferFloatBufferIntBufferLongBufferShortBuffer

选择器

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

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

标签: #javanio与io