返回顶部
首页 > 资讯 > 精选 >Android之从IO到NIO的模型机制实例分析
  • 277
分享到

Android之从IO到NIO的模型机制实例分析

2023-07-05 02:07:43 277人浏览 泡泡鱼
摘要

这篇文章主要讲解了“Android之从io到NIO的模型机制实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android之从IO到NIO的模型机制实例分析”吧!1 Basic IO模

这篇文章主要讲解了“Android之从ioNIO的模型机制实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android之从IO到NIO的模型机制实例分析”吧!

    1 Basic IO模型

    那么在Java(Kotlin)中,IO主要分为两种:Basic IO 和 Net IO;Basic IO是我们在开发当中常用的一些IO流,例如:

    FileInputStream://文件输入流FileOutputStream://文件输出流BufferedInputStream://缓存字节输入流BufferedOutputStream://缓存字节输入流,此类数据流为了提高读写效率,可以缓存数据到buffer,通过flush一起写入;内核分配内存为一页4K,但是Java缓冲区默认是8KObjectInputStreamObjectOutputStream:// 将数据序列化处理RandoMaccessFile://提供位移数据插入

    对于前面的几个数据流,我就不介绍用法了,对于最后一个RandomAccessFile,我想简单介绍一下,因为很多伙伴们可能不知道RandomAccessFile的存在,这里曾经有个面试题

    假设有一个5G的文件,我想在文章的末尾追加一段话,我该怎么处理?或者我指定任意位置添加一部分文字内容,该怎么处理?

    很多伙伴看到这个问题之后,一拍脑门说:先通过FileInputStream把文件读写进来,然后再在末尾追加一部分内容组合成新的字节流,然后再通过FileOutputStream写入到新的文件中。

    完蛋,直接pass掉!因为前提这里已经是5G的文件了,如果通过FileInputStream读写,大概率就会直接OOM! 所以如果知道RandomAccessFile的存在,这些就不是问题了。

    fun testAccessFile() {    //file文件    val file = File("/storage/emulated/0/NewTextFile.txt")    val accessFile = RandomAccessFile(file, "rw")    //先写一段    val text = "IO主要分为两种:Basic IO 和 Net IO;"    accessFile.write(text.toByteArray())    //再等5s    Thread.sleep(5000)    accessFile.seek(5)    accessFile.write("seek to pos 5".toByteArray())    accessFile.close()}

    首先我们常见一个RandomAccessFile,传入要读写的文件,首先写入一段话,然后等到5s后,调用RandomAccessFile的seek方法,此时指针就是移动到了文件第五个字符的位置,然后又写入了一些文字。

    Android之从IO到NIO的模型机制实例分析

    所以按照这种思想,回到前面的问题,即便是5G的文件,也不需要进行读写操作获取之前的全部数据就能够实现零内存追加;当然还有一个场景也会经常用到,就是断点续传。

    1.1 RandomAccessFile的缓冲区和BufferedInputStream缓冲区的区别

    首先我先简单介绍下BufferedInputStream的缓存区效果,系统内核缓存区默认为4K,当缓存区满4K之后会进行磁盘的写入;那么在Java中是对其做了优化处理,将缓存区变为8K,当缓存区超过8K之后,会将数据复制给到内核缓存。

    Android之从IO到NIO的模型机制实例分析

    fun testBuffer() {        val file = File("/storage/emulated/0/NewTextFile.txt")        val bis = BufferedOutputStream(FileOutputStream(file))        val text = "8888888888888888".toByteArray()        bis.write(text, 0, text.size)//        bis.flush()    }

    例如上面的案例,此时App的内存缓存区没有满,那么如果不调用flush,那么数据不会写到磁盘文件中,只有当缓冲区满了之后,才会复制到内核空间缓存区。

    fun testAccessFile() {    //file文件    val file = File("/storage/emulated/0/NewTextFile.txt")    val accessFile = RandomAccessFile(file, "rw")    //先写一段    val text = "IO主要分为两种:Basic IO 和 Net IO;"    accessFile.write(text.toByteArray())    //再等5s    Thread.sleep(5000)    accessFile.seek(5)    val channel = accessFile.channel    val mapper = channel.map(FileChannel.MapMode.READ_WRITE, channel.position(), channel.size())    mapper.put("seek to pos 5".toByteArray())}

    如果按照BufferedOutputStream的思想,我们往缓冲区写数据,没有flush就不会有复制的操作,那么我们实际看到的是数据还是写进去了。

    Android之从IO到NIO的模型机制实例分析

    其实MappedByteBuffer,是提供了一个类似于mmap性质的能力,实现了App缓冲区与内核缓冲区的桥接或者映射。

    Android之从IO到NIO的模型机制实例分析

    当App写入缓存数据的时候,直接映射到了内核缓存区,完成了磁盘的读写操作。

    1.2 Basic IO模型底层原理

    其实对于基础的IO模型,也就是Basic IO的实现是阻塞的,其实我们也可以自己验证,在主线程中进行读写操作就是阻塞的。

    那么对于IO来说,主要分为两个阶段:

    (1)数据准备阶段;这里是由Java实现的,写入到JVM中;

    (2)复制阶段;内核空间复制用户空间缓存数据,这部分需要调用内核函数(ioctl、sync),完成复制的工作。

    剩下的磁盘写入操作就完全是由内核完成的,如果对于读写操作有疑问的,可以去看看下面这篇对于Binder底层原理的介绍。

    Android Framework原理 -- Binder驱动源码分析

    对于传统的Socket来说,这种属于Net IO,本质也是阻塞性质的,例如App进程想要获取一些数据,

    Android之从IO到NIO的模型机制实例分析

    上图展示了read操作的整个调度过程:

    (1)当App调用系统方法想要获取某些数据的时候,首先系统内核会等待数据从网络中到达,这个过程内核处于阻塞的状态

    (2)等到数据到达之后,就会将网络数据复制到用户空间的缓冲区中,并通知App进程复制数据成功,此时App中其他业务才能够继续执行。

    所以整个过程中,App处于阻塞状态,而在高并发的场景中(客户端很少,这里拿服务端来举例),例如10000QPS(每秒10000次查询操作),此时如果采用IO阻塞模型,带来的后果就是CPU极速拉满最终可能导致熔断,所以针对这种情况,出现了NIO模型。

    2 NIO模型

    相对于IO模型来说,NIO模型做的优化是通过轮询机制获取内核的数据等待状态,看下图:

    Android之从IO到NIO的模型机制实例分析

    当一次询问发出之后,如果当前内核还是数据等待状态,那么内核空间会被”挂起“,此时App进程可以做其他的事情,等到下一次轮询时间到了之后,再次发起询问,如果此时已经拿到了数据,那么就会进行复制操作,将数据放入用户进程缓冲区。

    Android之从IO到NIO的模型机制实例分析

    那么对此,java.nio包下提供了很多非阻塞IO的api,例如我们前面提到的MappedByteBuffer。其实还是前面我们探讨的一个问题,在Android的场景下,很难碰到高并发的场景,所以基本上也很难用到这个,但是对于NIO模型的原理我们需要掌握透彻,在面试中可能会涉及到这些问题。

    3 OKIO

    最后介绍一个IO模型---OKIO,如果使用到OkHttp的伙伴们应该已经见到过这个,但是没有实际地去研究,为啥要引入这个okio三方库。

    首先okio是OkHttp团队基于Basic IO研发的一套自己的IO体系,为啥要搞一个这个玩意出来呢?通过前面我们分析Basic IO存在的一些问题,首先 Basic IO是阻塞的,而且在客户端端如果频繁地进行网络请求,而且网络请求是双向的,从客户端发出请求,服务端返回响应,那么这个过程必定会使用到InputStream和OutputStream。

    因为OkHttp是有自己的缓存策略的,如果使用到缓存,那么对于InputStream就需要一个buffer,对于OutputStream也需要一个buffer,每次读写操作都需要两个buffer来做支撑,因此针对这种场景,okio在底层做了处理。

    具体的处理就是不再使用byte[]数组存储数据,而是采用Segment数据结构。有熟悉Segment的伙伴应该知道,它是一个数组的双向链表,其中data就是一个byte数组,其中有next和pre两个指针。

    internal class Segment {  @JvmField val data: ByteArray    @JvmField var pos: Int = 0    @JvmField var limit: Int = 0    @JvmField var shared: Boolean = false    @JvmField var owner: Boolean = false    @JvmField var next: Segment? = null    @JvmField var prev: Segment? = null

    Android之从IO到NIO的模型机制实例分析

    当进行读写操作的时候,都会往Segment中写入,就是将InputStream和OutputStream需要创建的缓冲区合并。

    这里需要说明一点,okio属于OkHttp内部核心IO框架,并不是单独拿出来任意业务方可以使用,所以对于okio的具体实现原理,后续会放在OkHttp框架原理中做详细的介绍。

    感谢各位的阅读,以上就是“Android之从IO到NIO的模型机制实例分析”的内容了,经过本文的学习后,相信大家对Android之从IO到NIO的模型机制实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

    --结束END--

    本文标题: Android之从IO到NIO的模型机制实例分析

    本文链接: https://lsjlt.com/news/348943.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • Android之从IO到NIO的模型机制实例分析
      这篇文章主要讲解了“Android之从IO到NIO的模型机制实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android之从IO到NIO的模型机制实例分析”吧!1 Basic IO模...
      99+
      2023-07-05
    • Android进阶之从IO到NIO的模型机制演进
      目录引言1 Basic IO模型1.1 RandomAccessFile的缓冲区和BufferedInputStream缓冲区的区别1.2 Basic IO模型底层原理2 NIO模型...
      99+
      2023-01-30
      Android模型从IO到NIO机制 Android IO NIO
    • Tomcat中NIO模型的示例分析
      这篇文章给大家分享的是有关Tomcat中NIO模型的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、I/O复用模型解读Tomcat的NIO是基于I/O复用来实现的。对这点一定要清楚,不然我们的讨论就不在...
      99+
      2023-06-02
    • Android开发之Parcel机制实例分析
      本文实例讲述了Android开发之Parcel机制。分享给大家供大家参考。具体分析如下: 在java中,有序列化机制。但是在安卓设备上,由于内存有限,所以设计了新的序列化机制。...
      99+
      2022-06-06
      android开发 Android
    • Redis缓存IO模型的示例分析
      Redis缓存IO模型的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。前言redis作为应用最广泛的nosql数据库之一,大大小小也经历过很多次升级。在4.0版本之...
      99+
      2023-06-21
    • MySQL 8.0主从复制模型的示例分析
      这篇文章给大家分享的是有关MySQL 8.0主从复制模型的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、MySQL主从复制模型一切都要从MySQL的主从复制模型开始说...
      99+
      2024-04-02
    • Android编程之消息机制实例分析
      本文实例讲述了Android编程之消息机制。分享给大家供大家参考,具体如下: 一、角色描述 1.Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Mes...
      99+
      2022-06-06
      程之 消息机制 Android
    • php五大io模型之阻塞与非阻塞的示例分析
      小编给大家分享一下php五大io模型之阻塞与非阻塞的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!php实现五大io模型-1阻塞与非阻塞阻塞:是指应用程序执行IO操作需要彻底完成后才返回到用户空间非阻塞:是指应用程...
      99+
      2023-06-15
    • mysql主从复制丛库IO进程问题的实例分析
      这篇文章给大家介绍mysql主从复制丛库IO进程问题的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 配置mysql主从复制,启动slave进程后...
      99+
      2024-04-02
    • Android View刷新机制实例分析
      本文实例讲述了Android View刷新机制。分享给大家供大家参考,具体如下: 一、总体说明 在Android的布局体系中,父View负责刷新、布局显示子View;而当子Vi...
      99+
      2022-06-06
      view Android
    • JavaScript中从原型到原型链的示例分析
      这篇“JavaScript中从原型到原型链的示例分析”除了程序员外大部分人都不太理解,今天小编为了让大家更加理解“JavaScript中从原型到原型链的示例分析”,给大家总结了以下内容,具有一定借鉴价值,内容详细步骤清晰,细节处理妥当,希望...
      99+
      2023-06-14
    • swoole之进程模型的示例分析
      小编给大家分享一下swoole之进程模型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!初识server一文的时候我们说过,swoole是事件驱动的。在使...
      99+
      2023-06-14
    • Linux高性能网络IO和Reactor模型的示例分析
      小编给大家分享一下Linux高性能网络IO和Reactor模型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!目录一、基本概念介绍二、网络IO的读写过程三...
      99+
      2023-06-20
    • css的盒模型实例分析
      这篇文章主要介绍“css的盒模型实例分析”,在日常操作中,相信很多人在css的盒模型实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”css的盒模型实例分析”的疑惑有所帮...
      99+
      2024-04-02
    • java之JVM架构模型的示例分析
      小编给大家分享一下java之JVM架构模型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java可以用来干什么Java主要应用于:1. web开发;2....
      99+
      2023-06-14
    • 从源码角度分析Android的消息机制
      目录前言ThreadLocal的工作原理Looper的工作原理Handler的工作原理总结参考资料前言 说到Android的消息机制,那么主要的就是指的Handler的运行机制。其...
      99+
      2024-04-02
    • Android 图片的三级缓存机制实例分析
      Android 图片的三级缓存机制实例分析当我们获取图片的时候,如果不加以协调好图片的缓存,就会造成大流量,费流量应用,用户体验不好,影响后期发展。为此,我特地分享Android图片的三级缓存机制之从网络中获取图片,来优化应用,具体分三步进...
      99+
      2023-05-31
      android 图片 三级缓存
    • 基于角色的权限控制模型RBAC实例分析
      本篇内容主要讲解“基于角色的权限控制模型RBAC实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于角色的权限控制模型RBAC实例分析”吧!一、RBAC权限模型简介RBAC权限模型(Rol...
      99+
      2023-06-29
    • Redis中主从同步机制的示例分析
      小编给大家分享一下Redis中主从同步机制的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!之前的文章中详细分析了redi...
      99+
      2024-04-02
    • iptables从入门到应用的实例分析
      iptables从入门到应用的实例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。iptables从入门到应用 一、简介 1.1、是什么?...
      99+
      2023-06-06
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作