javaNio学习笔记(一) 学习参考文档: http:tutorials。jenkov。comjavanioindex。html什么是javaNio javaNio是javanewIO。是java1。4新增的API。它提供了另一种不同于标准IO的实现方式来实现IO知其然知其所以然 为什么要使用javaNio? 弄懂了为什么要使用JavaNIO也就是知道我们为啥要学NIO了。 首先NIO出现就是提供了替代标准IO的一种IO实现方式。那么为什么要替换标准IO呢? 我们来看下下面的例子:serverpublicclassBio{publicstaticvoidmain(String〔〕args){try{ServerSocketservernewServerSocket(2999);System。out。println(server监听2999端口等待客户端连接Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());Socketsocketserver。accept();System。out。println(server监听2999端口等待客户端接受数据Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());从套接字中获取输入流InputStreaminputStreamsocket。getInputStream();byte〔〕bytesnewbyte〔1024〕;inputStream。read(bytes);System。out。println(getmessagefromclient:newString(bytes)Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());inputStream。close();socket。close();server。close();}catch(IOExceptione){e。printStackTrace();}}}clientpublicclassClient{publicstaticvoidmain(String〔〕args){try{建立连接System。out。println(客户端准备连接服务器2999端口Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());SocketsocketnewSocket(127。0。0。1,2999);System。out。println(客户端连接服务器2999端口Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());向socket写入数据OutputStreamoutputStreamsocket。getOutputStream();System。out。println(客户端连接服务器开始写入数据Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());socket。getOutputStream()。write(hi,behappy。getBytes(UTF8));System。out。println(客户端连接服务器开始写入完成Instant。now()。atOffset(ZoneOffset。ofHours(8))。toInstant());outputStream。close();socket。close();}catch(IOExceptione){System。out。println(e。getMessage());}}} 先启动server,然后再启动client(为了让结果比较清晰建议打断点运行),返回结果如下server返回结果:server监听2999端口等待客户端连接20200611T14:35:58。428Zserver监听2999端口等待客户端接受数据20200611T14:36:16。120Zgetmessagefromclient:hi,behappyclient返回结果客户端准备连接服务器2999端口20200611T14:36:02。026Z客户端连接服务器2999端口20200611T14:36:35。664Z客户端连接服务器开始写入数据20200611T14:36:40。984Z客户端连接服务器开始写入完成20200611T14:36:42。969Z 运行断点的时候会发现,当server执行到server。accept()和inputStream。read()的时候程序会阻塞,让程序等待,这样会影响执行效率。这也就是为什么会有NIO来替代IO。先自己思考解决方案 如果是让我来解决这个问题,该如何处理呢? 可以开线程,每一个线程来处理一个client的连接。这样即使阻塞也是只阻塞当前线程。这样即使阻塞也只是阻塞当前线程,而不会对其他线程造成影响。当然这么做就会消耗系统资源,因为线程是有限的,我们不可能无限的开启线程,若客户端一直未连接就需要做超时处理,将线程关闭。JavaNIO是如何来做的? 这个问题可能需要等到学习完javaNIO之后才可能回答得出来。那么下面我就开始学习JavaNIO。javaNIO简单导读 参考上面文档地址传统IO是面向流的,而javaNIO则是面向channels和buffers的。数据都是从channel中读取到buffer或者从channel中写入buffer。javaNIO是非阻塞IO,即不会产生上面的问题。线程可以让channel(有的人叫通道)去读取buffer中的数据,这个时候线程可以做其他事情。当数据层从channel读取到buffer的时候线程在继续处理这部分事情。对于写也是一样。JavaNIO还提供了一个selector。selector是一个对象,可以监控多个通道的事件(如:连接打开,数据到达等)。这样可以让单个线程监视多个channeljavaNIO基本概念 javaNIO主要的核心组件如下:Channels(通道、管道、频道)buffers(数据缓冲区)Selector(选择器,从导读的概念来看感觉有点像监听器) 当然javaNIO还有一些其他组件,后面我会慢慢进行学习。 channel和buffer就可以理解潮汐车道俩头的地点。数据可以从频道(channel)中写入缓冲区(buffer)。 也可以从缓冲区读取到频道中。 主要实现的管道类型FileChannelDatagramChannelSocketChannelServerSocketChannel 核心的缓冲区ByteBufferCharBufferDoubleBufferFloatBufferIntBufferLongBufferShortBuffer 选择器 选择器的作用就是能让单个线程来处理多线程的事情。要使用选择器,需要注册频道。然后调用它的select()方法。此方法将阻塞,直到为其中一个已注册通道准备好事件为止。方法返回后,线程就可以处理这些事件。(有传入的连接,接收到的数据等等) 这些类型后续学习中我会进行练习并尽量做详细了解