When studying both the Java NIO and IO API's, a question quickly pops into mind:
When should I use IO and when should I use NIO?
In this text I will try to shed some light on the differences between Java NIO and IO, their use cases, and how they affect the design of your code.
Main Differences of Java NIO and IO
The table below summarizes the main differences between Java NIO and IO. I will get into more detail about each difference in the sections following the table.
IO | NIO |
Stream oriented | Buffer oriented |
Blocking IO | Non blocking IO |
Selectors |
Stream Oriented vs. Buffer Oriented
The first big difference between Java NIO and IO is that IO is stream oriented, where NIO is buffer oriented. So, what does that mean?
Java IO being stream oriented means that you read one or more bytes at a time, from a stream. What you do with the read bytes is up to you. They are not cached anywhere. Furthermore, you cannot move forth and back in the data in a stream. If you need to move forth and back in the data read from a stream, you will need to cache it in a buffer first.
Java NIO's buffer oriented approach is slightly different. Data is read into a buffer from which it is later processed. You can move forth and back in the buffer as you need to. This gives you a bit more flexibility during processing. However, you also need to check if the buffer contains all the data you need in order to fully process it. And, you need to make sure that when reading more data into the buffer, you do not overwrite data in the buffer you have not yet processed.
Blocking vs. Non-blocking IO
Java IO's various streams are blocking. That means, that when a
thread invokes a read()
or write()
, that thread is blocked until there is some
data to read, or the data is fully written.
The thread can do nothing else in the meantime.
Java NIO's non-blocking mode enables a thread to request reading data from a channel, and only get what is currently available, or nothing at all, if no data is currently available. Rather than remain blocked until data becomes available for reading, the thread can go on with something else.
The same is true for non-blocking writing. A thread can request that some data be written to a channel, but not wait for it to be fully written. The thread can then go on and do something else in the mean time.
What threads spend their idle time on when not blocked in IO calls, is usually performing IO on other channels in the meantime. That is, a single thread can now manage multiple channels of input and output.
Selectors
Java NIO's selectors allow a single thread to monitor multiple channels of input. You can register multiple channels with a selector, then use a single thread to "select" the channels that have input available for processing, or select the channels that are ready for writing. This selector mechanism makes it easy for a single thread to manage multiple channels.
How NIO and IO Influences Application Design
Whether you choose NIO or IO as your IO toolkit may impact the following aspects of your application design:
- The API calls to the NIO or IO classes.
- The processing of data.
- The number of thread used to process the data.
The API Calls
Of course the API calls when using NIO look different than when
using IO. This is no surprise.
Rather than just read the data byte for byte from e.g. an InputStream
,
the data
must first be read into a buffer, and then be processed from there.
The Processing of Data
The processing of the data is also affected when using a pure NIO design, vs. an IO design.
In an IO design you read the data byte for byte from an InputStream
or
a Reader
. Imagine you were processing a stream of line
based textual data.
For instance:
Name: Anna Age: 25 Email: anna@mailserver.com Phone: 1234567890
This stream of text lines could be processed like this:
InputStream input = ... ; // get the InputStream from the client socket BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String nameLine = reader.readLine(); String ageLine = reader.readLine(); String emailLine = reader.readLine(); String phoneLine = reader.readLine();
Notice how the processing state is determined by how far the program
has executed. In other words,
once the first reader.readLine()
method returns, you
know for sure that a full line
of text has been read. The readLine()
blocks until a
full line is read, that's why.
You also know that this line contains the name. Similarly, when the
second readLine()
call returns, you know that this line contains the age etc.
As you can see, the program progresses only when there is new data to read, and for each step you know what that data is. Once the executing thread have progressed past reading a certain piece of data in the code, the thread is not going backwards in the data (mostly not). This principle is also illustrated in this diagram:
Java IO: Reading data from a blocking stream. |
A NIO implementation would look different. Here is a simplified example:
ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buffer);
Notice the second line which reads bytes from the channel into the ByteBuffer
.
When that method call returns you don't know if all the data you
need is inside the buffer.
All you know is that the buffer contains some bytes. This makes
processing somewhat harder.
Imagine if, after the first read(buffer)
call, that all
what was read into the
buffer was half a line. For instance, "Name: An". Can you process
that data? Not really.
You need to wait until at leas a full line of data has been into the
buffer, before it
makes sense to process any of the data at all.
So how do you know if the buffer contains enough data for it to make sense to be processed? Well, you don't. The only way to find out, is to look at the data in the buffer. The result is, that you may have to inspect the data in the buffer several times before you know if all the data is inthere. This is both inefficient, and can become messy in terms of program design. For instance:
ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buffer); while(! bufferFull(bytesRead) ) { bytesRead = inChannel.read(buffer); }
The bufferFull()
method has to keep track of how much
data is read into the buffer,
and return either true
or false
, depending
on whether the buffer is
full. In other words, if the buffer is ready for processing, it is
considered full.
The bufferFull()
method scans through the buffer, but
must leave the buffer in
the same state as before the bufferFull()
method was
called. If not, the next
data read into the buffer might not be read in at the correct
location. This is not impossible,
but it is yet another issue to watch out for.
If the buffer is full, it can be processed. If it is not full, you might be able to partially process whatever data is there, if that makes sense in your particular case. In many cases it doesn't.
The is-data-in-buffer-ready loop is illustrated in this diagram:
Java NIO: Reading data from a channel until all needed data is in buffer. |
Summary
NIO allows you to manage multiple channels (network connections or files) using only a single (or few) threads, but the cost is that parsing the data might be somewhat more complicated than when reading data from a blocking stream.
If you need to manage thousands of open connections simultanously, which each only send a little data, for instance a chat server, implementing the server in NIO is probably an advantage. Similarly, if you need to keep a lot of open connections to other computers, e.g. in a P2P network, using a single thread to manage all of your outbound connections might be an advantage. This one thread, multiple connections design is illustrated in this diagram:
Java NIO: A single thread managing multiple connections. |
If you have fewer connections with very high bandwidth, sending a lot of data at a time, perhaps a classic IO server implementation might be the best fit. This diagram illustrates a classic IO server design:
Java IO: A classic IO server design - one connection handled by one thread. |
相关推荐
Peakdet 是一个 NodeJS 库,用于检测数据中的峰谷。 Peakdet 采用的来检测峰值并将其打包为库并添加测试。...// Call the peakdet function, the second argument is the minimum differece // between the
To discover the spectra of them present obvious difference and the spectra for the blood of the different kind of the patient also present obvious differece, but the spectra of the specifieness ...
#CodeQuiz CodeQuiz 是一款使用 Kivy 框架制作的游戏。 他是一个测验由四个选项组成,Ruby、Python、Javascript 和 C#。... 提交它git commit -m 'the differece' 推送它git push origin name-your-feature 创建
【资源说明】 基于C语言课程设计学生成绩管理系统、详细文档+全部资料+高分项目.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
项目均经过测试,可正常运行! 环境说明: 开发语言:java JDK版本:jdk1.8 框架:springboot 数据库:mysql 5.7/8 数据库工具:navicat 开发软件:eclipse/idea
互联网技术经过数十年的发展,已经积累了深厚的理论基础,并在实际应用中无处不在,极大地消除了地理信息的障碍,实现了全球即时通讯,极大地便利了人们的日常生活。因此,利用计算机技术设计的线上招聘问答系统,不仅在管理上更加系统化和操作性强,更重要的是在数据保存和使用上能够节省大量时间,使得系统变得非常高效和实用。 线上招聘问答系统采用MySQL作为数据管理工具,Java作为编码语言,以及SSM框架作为开发架构。系统主要实现了简历管理、论坛帖子管理、职位招聘管理、职位招聘留言管理、招聘岗位管理、所在行业管理以及求职意向管理等功能。 该系统的设计不仅方便了操作人员,而且合理性高,能有效避免误操作,确保数据在录入时就符合设计要求,从而最大限度地减少源头性输入错误,使数据更加可控和可靠,将出错率降至最低。
simulink实现标准IEEE33配电网系统,50HZ,将各节点数据统计起来输出到工作区,再matlab中跑出某时刻节点电压分布,适合用于观察某时刻节点电压变化情况。 #特别是当用于接入双馈风机时,用powergui无法进行潮流计算,通过此方法能过很好的解决此问题。 有参考文献。
给袋式真空包装机UG10全套技术资料100%好用.zip
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea、微信开发者工具 数据库:MySql5.7以上 部署环境:maven 数据库工具:navicat
Java 入门教程.md
2024.10月份更新 最低unity版本2021.3.4
xxscd_7.0.apk
【资源说明】 基于C语言课程设计-职工管理系统、详细文档+全部资料+高分项目.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
自动氩弧焊机sw18全套技术资料100%好用.zip
MATLAB Simulink搭建电动车制动能量回收控制策略 整车参数 整车参数及性能指标 基本参数 参数值 整备质量 kg 1550 满载质量 kg 1920 轴距 m 2.670 轮胎滚动半径 m 0.3 续驶里程 km 300 最高车速 (km·h-1) 150 最大爬坡度 % 30 0~100 km·h-1加速时间 s 12 电机、电池参数匹配 轮毂电机、动力电池参数 参数 参数值 轮毂电机 额定功率 kW 20 峰值功率 kW 50 额定转速 r·(min-1) 450 峰值转速 r·(min-1) 1500 额定转矩 (N·m) 400 峰值转矩 (N·m) 900 动力电池 额定电压 V 336 容量 Ah 170 最大充电功率 kW 7.5 电机最大制动力矩 式中,Temax为电机最大制动力矩;Pmax为电机峰值功率;PBmax为电池最大充电功率;ηb为电池充电效率;Tmax为电机峰值转矩;n为电机转速;nd为电机基速。 充电电流 式中,Im为充电电流;ηm为电机发电效率;T为单个电机制动力矩;Uec为电池的端电压。 动力电池SOC 采
CSGO赛事管理系统的作用就是提供一个在线CSGO赛事管理的信息储存以及搜索的系统,用来协助对CSGO赛事信息进行统一管理。一个完善的CSGO赛事管理系统,可以对CSGO赛事进行精细化的管理。 环境说明: 开发语言:java JDK版本:jdk1.8 框架:springboot 数据库:mysql 5.7/8 数据库工具:navicat 开发软件:eclipse/idea
多层陶瓷电容预热清扫机2DCAD+BOM清单proe4.0 可编辑全套技术资料100%好用.zip
“最多跑一次”小程序是一款基于微信平台的便民服务应用程序,旨在为用户提供政务服务、社区服务、生活服务的线上办理和查询功能,让用户能够足不出户即可享受各种便民服务。该小程序的名称源自“最多跑一次”改革理念,旨在减少群众办事过程中的跑腿次数,提高办事效率,方便用户快速、便捷的完成各项事务。政务服务方面,该小程序涵盖了各级政府部门的线上办事服务,用户可以通过小程序完成各类证件申办、查询政务信息、预约办事等功能,避免了排队等待和办公室跑腿的繁琐程序。社区服务方面,该小程序整合了社区文化活动、志愿者服务、社区警务等多项社区服务事项,为用户提供便捷的社区服务。生活服务方面,用户可以通过该小程序查询公交车时刻、预约停车位、快递物流查询等日常生活服务,方便了用户的出行和生活。此外,该小程序还具有身份验证、在线支付、消息通知等功能,用户可以通过微信小程序完整的完成各种服务事务,无需额外下载其他应用,提升了用户的使用体验。总之,“最多跑一次”小程序以其丰富的服务内容、便捷的操作流程和安全的使用环境,满足了用户办事的多样化需求,让用户享受到智慧城市带来的便利和舒适。
项目均经过测试,可正常运行! 环境说明: 开发语言:java JDK版本:jdk1.8 框架:springboot 数据库:mysql 5.7/8 数据库工具:navicat 开发软件:eclipse/idea
09 - 淘宝直播:第一次直播话术怎么写