IO 模型

传统 IO读写

       磁盘IO主要的延时是由(以15000rpm硬盘为例): 机械转动延时(机械磁盘的主要性能瓶颈,平均为2ms) + 寻址延时(2~3ms) + 块传输延时(一般4k每块,40m/s的传输速度,延时一般为0.1ms) 决定。(平均为5ms)

 /**
* 传统的IO读取
* @param oriStr
* @param destStr
*/
public void customRead(String oriStr,String destStr){
FileInputStream in = null;
FileOutputStream os = null;
try {
in = new FileInputStream(oriStr);
os = new FileOutputStream(destStr);
//一次读取1K 数据
byte[] bytes = new byte[1024];
while(in.read(bytes)!=-1){
os.write(bytes);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
in.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 带缓冲区的IO读取
* @param oriStr
* @param destStr
*/
public void bufferRead(String oriStr,String destStr){
BufferedInputStream in = null;
BufferedOutputStream os = null;
try {
in = new BufferedInputStream(new FileInputStream(oriStr));
os = new BufferedOutputStream(new FileOutputStream(destStr));
//一次读取1K 数据
byte[] bytes = new byte[1024];
while(in.read(bytes)!=-1){
os.write(bytes);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
in.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

QA  很多人看了上述2段代码后,可能要反驳啦,customRead有缓存啊,不是一次性读取1024个字节到byte数组了吗

QA  bufferRead 为啥一定比customeRead 速度快

其实要理解上面2个问题,很简单,

①:fileInputStream.read(byte[]) 是一个骗人的方法,他是通过循环操作调用read()方法,每次读取一个字节,然后填满byte数组。

②:BufferedInputStream.read(byte[]) 他是预先从磁盘读取最大8K的数据,然后保存在本地的一个叫buf 数组中,后面读取数据的时候直接从这个buf中获取

fileInputStream 每次从磁盘获取数据,BufferedInputStream 每次才从本地缓存拿数据,一目了然,BufferedInputStream 明显快多啦(源码不是很复杂,有兴趣的朋友可以看看源码就知道啦)

网络IO

    网络IO主要延时由: 服务器响应延时 + 带宽限制 + 网络延时 + 跳转路由延时 + 本地接收延时 决定。(一般为几十到几千毫秒,受环境干扰极大),考虑到网络IO瓶颈,就有很多传输模型,BIO,NIO等等 在这些模型中就不得不提 ByteBuffer,

那ByteBuffer 是啥,其实这个东西经常用在网络传输NIO模型上,网络传输为了提高效率,不可能一个一个在磁盘上读取,那么需要读取一块数据存储到内存里,ByteBuffer(ByteBuffer内部维护一个byte[],是不是很熟悉,这个套路)就是应用缓存,负责在内存中保存读取的那一整块数据

//伪代码
public void nioRead() {
FileChannel channel=null;
try{
RandomAccessFile raf=new RandomAccessFile("src/exp_io.txt","rw");
//获取通道
channel=raf.getChannel();
if(0==raf.length()){
return;
}
//分配缓存空间
ByteBuffer buffer=ByteBuffer.allocate((int)raf.length());
byte [] bytes=new byte[(int)raf.length()];
//将数据写入缓存
int bytesRead=channel.read(buffer);
int i=0;
while (bytesRead!=-1){
buffer.flip();
while (buffer.hasRemaining()){
//从缓存读取数据
bytes[i]=buffer.get();
i++;
}
//将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面
//现在向缓存中写入数据时不会覆盖未读的数据
buffer.compact();
bytesRead=channel.read(buffer);
}
System.out.println(new String(bytes));
}catch (Exception e){ }finally {
try{
if (channel!=null){
channel.close();
}
}catch (Exception e){ }
}
}

  

总结

java 为提高IO读写的效率,就一个办法,想办法一次性多读取数据,然后缓存起来。其实ByteBuffer 和BufferedInputStream的根本方法都是一致的,就是搞一个本地的应用缓存,来解决IO瓶颈。

考虑一个问题 ByteBuffer 是堆内分配内存,如果,我直接用堆外内存(减少系统缓存copy到应用缓存中)作为应用缓存,那么能不能提高IO瓶颈。(netty的套路,有兴趣大家可以研究一下哈)

参考资料

网络IO和磁盘IO详解 https://www.cnblogs.com/sunsky303/p/8962628.html

BufferByte用法小结 https://blog.csdn.net/mrliuzhao/article/details/89453082

聊聊 传统IO和网络IO的更多相关文章

  1. 多路复用 阻塞/非阻塞IO模型 网络IO两个阶段

    1.网络IO的两个阶段 waitdata copydata send 先经历:copydata阶段 recv 先经历:waitdata阶段 再经历 copydata阶段 2.阻塞的IO模型 之前写的都 ...

  2. 磁盘 IO 和网络 IO 该如何评估、监控、性能定位和优化?

    生产中经常遇到一些IO延时长导致的系统吞吐量下降.响应时间慢等问题,例如交换机故障.网线老化导致的丢包重传:存储阵列条带宽度不足.缓存不足.QoS限制.RAID级别设置不当等引起的IO延时. 一.评估 ...

  3. Socket-IO 系列(一)Linux 网络 IO 模型

    Socket-IO 系列(一)Linux 网络 IO 模型 一.基本概念 在正式开始讲 Linux IO 模型前,先介绍 5 个基本概念. 1.1 用户空间与内核空间 现在操作系统都是采用虚拟存储器, ...

  4. 阿里、腾讯热门面试题:聊聊Unix与Java的IO模型?(含详细解析)

    众所周知 如果去百度.腾讯等一线大厂面试,一定会深入考候选人的基础技术功底,其中尤为关键和重视的就是IO相关的技术和知识. 而要搞明白IO相关的概念,首先就得弄清楚同步与异步,阻塞与非阻塞到底是什么意 ...

  5. 我对网络IO的理解

    Unix/Linux系统下IO主要分为磁盘IO,网络IO,我今天主要说一下对网络IO的理解,网络IO主要是socket套接字的读(read).写(write),socket在Linux系统被抽象为流( ...

  6. 网络io控制器

    网络io控制器 网络io控制器 ZLAN6842,ZLAN6844是8路远程网络IO控制器.含有8路DI.8路DO,8路AI输入.其中DI支持干节点和湿节点,带光耦隔离:DO为继电器输出,具有5A 2 ...

  7. 漫谈Java IO之普通IO流与BIO服务器

    今天来复习一下基础IO,也就是最普通的IO. 网络IO的基本知识与概念 普通IO以及BIO服务器 NIO的使用与服务器Hello world Netty的使用与服务器Hello world 输入流与输 ...

  8. 并发编程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路复用io

    1.io模型提交任务得方式: 同步:提交完任务,等结果,执行下一个任务 异步:提交完,接着执行,异步 + 回调 异步不等结果,提交完任务,任务执行完后,会自动触发回调函数同步不等于阻塞: 阻塞:遇到i ...

  9. 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

随机推荐

  1. deconv的弊端

    https://chuansongme.com/n/2630693453218 学习到deconvlution会带来棋盘鬼影,比较重要的解决方法就是resize-deconvlution

  2. Java数据结构-02单链表(一)

    一.链式存储: ①简述:线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的.存储单元由两部分组成,数据源和指针,数据源放数据,指针指向下个 ...

  3. 拖拽编写SVG图形化工具(二)

    getAttributesNs/setAttributesNs element.setAttributeNS(namespace,name,value) namespace 是指定属性的命名空间的一个 ...

  4. 【应用服务 App Service】App Service证书导入,使用Key Vault中的证书

    问题描述 正常情况下,如果需要为应用服务安装SSL证书,可以在证书准备好的情况,通过门户上传即可,详细步骤可以参考微软官方文档(在 Azure 应用服务中添加 TLS/SSL 证书:https://d ...

  5. 【转】Getting an Image on the Screen

    FROM:http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php Getting an Image o ...

  6. STM32入门系列-GPIO工作模式及LED电路原理

    GPIO工作模式 由于GPIO内部的结构关系,决定了GPIO可配置成以下几种模式. 输入模式 在输入模式时,施密特触发器打开,输出被禁止.可通过输入数据寄存器GPIOx_IDR读取I/O状态.输入模式 ...

  7. while语句的一个使用技巧

    作用类似于可以输入一个不定量长度的数组,但是严格来说 不可能出现任意长度. 内存是有限的 超出一定长度后,不可能存的下,虽然这个值可能是超级大的,但总有限度. 这里我们利用while(cin>& ...

  8. Java学习的第二天

    1.今天学习了变量与常量看了大道至简 字节型:byte 1字节 短整型:short 2字节  整型:int 4字节长整型:long 8字节单精度浮点型:float 4字节双精度浮点型:double 8 ...

  9. 【漏洞复现】Shiro<=1.2.4反序列化漏洞

    0x01 概述 Shiro简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从 ...

  10. Java入门(5)

    阅读书目:Java入门经典(第7版) 作者:罗格斯·卡登海德 protected变量只能在其所在的类,该类的子类,以及同一个包里的其他类中使用.包是一组用于完成相同目标的相关类. private变量只 ...