基础篇--Java IO--概览

字符流、字节流、输入流、输出流

Java 中使用IO(输入输出)来读取和写入,读写磁盘文件、内存、网络数据。输入输出是相对内存而言,往内存中读数据就为输入流,从内存中往外写就是输出流。
根据处理类型分为字符流、字节流。

  • 字节流处理所有类型数据,以Stream结尾;

  • 字符流处理文本数据,以Reader、Writer结尾;
    Java IO类见下图:
    Java IO类
    同步、异步、阻塞、非阻塞
    synchronous、asynchronous、blocking、non-blocking

    同步、异步关注的是消息通信机制
    同步,是在发起调用后,在得到结果前,该调用不会返回。等到调用返回后,就能拿到返回值。调用者主动等待调用结果。
    异步, 是在发起调用后,调用直接返回,所以无返回结果。后续通过状态、回调通知调用者。

    阻塞、非阻塞关注的是程序在等待调用结果(返回值、消息)时的状态
    阻塞调用,是指在调用结果返回前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
    非阻塞调用,是指在调用结果返回前,该调用不会阻塞当前线程。

    换句话说:
    同步、异步区别:是否需要等待调用结果,才能进行下一步。
    阻塞、非阻塞:进程\线程要访问的数据就绪前,进程\线程是否需要等待。

Linux的5种IO模型

  1. 阻塞IO模型
  2. 非阻塞IO模型
  3. IO复用模型
  4. 信号驱动IO模型
  5. 异步IO模型

1.阻塞IO模型
Linux中,默认情况下socket是阻塞的,一个典型的读操作流程如下:
socket读
当用户进程调用了recvfrom这个系统调用,kernel就开始了I/O的第一个阶段:准备数据。对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候kernel就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。
当kernel一直等到数据准备好了,它就会将数据从kernel系统缓冲区中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。所以,blocking IO的特点就是在I/O执行的两个阶段都是block。
Windows Socket API
socket()函数和WSASocket()函数创建套接字时,默认的套接字是阻塞的。线程会阻塞等待,直到Windows Sockets API执行完成。
bind()、listen()函数,不会阻塞线程
可能会阻塞套接字的Windows Socket API调用分为4类

  1. 输入操作:recv()、recvfrom()、WSARecv()和WSARecvfrom()函数。以阻塞套接字为参数的该函数接受数据。如果此时套接字缓冲区中无数据,则调用线程一直睡眠到数据到来

  2. 输出操作:send()、sendto()、WSASend()和WSASendto()函数。调用该函数发送数据。如果套接字缓冲区无可用空间,则调用线程会一直睡眠到有可用空间。

  3. 接受连接:accept()和WSAAcept()函数。以阻塞套接字为参数的该函数等待接受对方的连接请求。无则线程休眠。

  4. 外出连接:connect()和WSAConnect()函数。对于TCP连接,客户端以阻塞套接字为参数,调用该函数向服务器发起连接。
    该函数在接收到服务器的应答前,不会返回。 这意味着TCP连接总会等待至少到服务器的一次往返时间。

    阻塞模式的套接字,开发实现简单。但是并发能力较弱,扩展性弱。

2.非阻塞IO模型
Linux下,可以设置socket为non-blocking。这种情况下的读取流程如下:
非阻塞IO,读取流程
用户进程调用recvfrom()时,如果kernal数据还未准备好,则直接返回error。用户线程不断重试,直到kernal准备好后,就马上将数据拷贝到用户内存,然后返回。所以这种模式下,用户线程需要不断主动询问kernal数据好了没。

3.IO复用模型(IO multiplexing)
IO复用模型又称event driven I/O,是在实际中使用最多的I/O模型。基本原理是select/epoll这个方法不断轮训所负责的socket,当某个socket有数据到达时,就通知用户线程。流程如下:
I/O复用模型
当用户线程调用select(),整个线程就会block,同时kernal会监听所有select负责的socket,一旦有socket的数据准备好了,select()就会返回。这时候用户线程再去调用read()操作,将数据从kernal拷贝到用户线程。
当线程数量较少时,这种方式可能比阻塞I/O模型效率更低,因为多了select()操作。select/epoll的优势是能处理更多的连接,在高并发场景效率更高。

4.信号驱动I/O模型(Signal-driven I/O)
首先我们需要允许套接字使用信号驱动IO,并安装一个信号处理函数,然后进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,在信号处理函数中调用IO操作函数处理数据。流程如下:(这种模型在实际中并不常用)
信号驱动I/O
5.异步I/O模型(Asynchronous I/O)
这种模型不常用,流程如下:
异步I/O流程图
用户线程发起read操作后,立刻就可以去做别的事情。从kernal角度,当它收到一个asynchroous read请求之后,会立刻返回,不会阻塞用户进程。然后kernal等待数据准备完成,将数据拷贝到用户内存,之后给用户进程发送一个signal,告诉它read操作完成了。

总结
1:blocking和non-blocking的区别
blocking IO会阻塞住对应的进程直到操作完成,non-blocking IO在kernal还未准备好数据的时候,直接返回。

1:synchronous I/O 和asynchronous IO的区别
区别在于synchronous I/O做I/O操作的时候会将进程阻塞。所以,blocking I/Onon-blocking I/OI/O multiplexingSignal-driven I/O都属于synchronous I/O,只有Asynchronous I/O属于asynchronous IO

扩展:select、poll、epoll简介
epoll跟select都能提供多路I/O复用的解决方案。在现在的Linux内核里有都能够支持,其中epoll是Linux所特有,而select则应该是POSIX所规定,一般操作系统均有实现。
1.select
select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:

  1. 单个进程可监视的fd数量被限制,即能监听端口的大小有限:
    一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048

  2. 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低:
    当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll与kqueue做的。

  3. 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大

    2.poll
    poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了多次无谓的遍历。
    它没有最大连接数的限制,原因是它是基于链表来存储的,但是同样有一个缺点:

    1. 大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
    2. poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
    

    3.epoll
    epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,并且只会通知一次。还有一个特点是,epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知。
    epoll的优点:

  4. 没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)

  5. 效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数
    即Epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,Epoll的效率就会远远高于select和poll

  6. 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销

select、poll、epoll 区别

select内核需要将消息传递到用户空间,都需要内核拷贝动作
poll同上
epollepoll通过内核和用户空间共享一块内存来实现

4、Linux I/O模型总结

综上,在选择select,poll,epoll时要根据具体的使用场合以及这三种方式的自身特点:

1、表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。
2、select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314079.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET轻松写博客园爬虫

爬虫,是一种按照一定的规则,自动地抓取网站的程序或者脚本。.NET写爬虫非常简单,并能轻松优化性能。今天我将分享一段简短的代码,爬出博客园前200页精华内容,然后通过微小的改动,将代码升级为多线程爬虫&am…

kettle同步数据中文乱码问题解决

最近在使用kettle进行数据同步的时候,发现同步来的中文数据产生了乱码。试了下网上的解决方案,最终解决了这个问题。步骤如下: 1:kettle中配置源数据库、目标数据库编码 2:编辑“表输入”,去掉勾选“允许建…

WTM重磅更新,LayuiAdmin免费用 and more

从善如登,从恶如崩。对于一个开发人员来说,那就是做一个好的系统不容易,想搞砸一个系统很简单,删库跑路会还不会么。对于我们开源框架的作者来说,做一个好的框架就像登山(也许是登天)&#xff0…

kettle数据库操作OPTION SQL_SELECT_LIMIT=DEFAULT问题解决

今天在使用kettle配置数据库映射的时候,有如下报错: Couldnt get field info from [select * from pre_user_base_bak]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax …

.netcore 分布式事务CAP2.6 快速入门

CAP介绍:CAP是一个用来解决微服务或者分布式系统中分布式事务问题的一个开源项目解决方案。可以解决跨服务器的数据一致性问题。一个简单的列子,如:订单系统创建订单后需要通知邮件通知用户下单成功,解决方案有下面几种&#xff1…

#3601. 一个人的数论

#3601. 一个人的数论 首先这个转化还是很巧妙的,或者很套路的,直接莫比乌斯反演,然后看到了自然数幂之和的形式,那么我们就可以转化为多项式处理,项数就减少到了d1,然后看到题目给出的都是质因数分解结果&a…

2019-03-5-算法-进化(最长公共前缀)

题目描述 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 示例 1: 输入: ["flower","flow","flight"] 输出: "fl"示例 2: 输入: ["dog","racecar","…

自然数幂之和

自然数幂之和 https://blog.csdn.net/suncongbo/article/details/97622131 这个文章的整理非常全面。

从你的全世界路过—一群程序员的稻城亚丁游记

转眼之间又即将到九月,又到了这个适合去川西旅游的最佳季节。最近有一些朋友问我稻城亚丁的旅游情况,因此我将去年写的这一篇游记再次发出来,希望对那些有计划去川西旅游的朋友们有帮助!温馨提示:本文图片较多&#xf…

P2303 [SDOI2012] Longge(数论/欧拉函数)

P2303 [SDOI2012] Longge 一道看似非常基础的数论题,但是蕴含了非常多的知识,求解 ∑i1ngcd(i,n)\sum_{i1}^ngcd(i,n) i1∑n​gcd(i,n) 这个东西我们轻松地就能化简成id∗φid*\varphiid∗φ的形式,然后考虑如何快速求解,那么可以…

基于SQLite+EF6实现一套自己的Key-Value存储管理工具包(1)

在项目中,经常会需要对一些特定的业务对象进行属性的扩展,而且这些属性的扩展还具备极不可预测性、相互关系松散等特点。大部分的开发人员是最讨厌这类涉及到数据字段扩展的需求变更。这种调整,轻则数据要加字段,重则程序代码要做…

【C】Natasha V1.3.6.0 的升级日志

文章转载授权级别:C 预计阅读时间:8分钟开源库满足于个人,而完善于大众。Natasha 自稳定版发布之后,众多老铁参与增强改进,感谢如下老铁的反馈:1. 异常搜集在 wenjq0911 建议下,添加…

.NET 程序员如何学习Vue

之所以取这个标题,是因为本文来自内部培训的整理,培训的对象是公司的 .NET 程序员,.NET 程序员学习 Vue 是为了在项目中做二次开发时能够更好地跟产品对接。Vue 是现在比较流行的前端框架,也是非常容易入门的前端框架,…

.Net之微信小程序获取用户UnionID

前言:在实际项目开发中我们经常会遇到账号统一的问题,如何在不同端或者是不同的登录方式下保证同一个会员或者用户账号唯一(便于用户信息的管理)。这段时间就有一个这样的需求,之前有个客户做了一个微信小程序商城&…

自由源自于自律 及其他三则分享

Office 365 官方公众号的新创深度内容推荐竹板这么一打呀,别的咱不夸,单说我们的Office 365官方公众号(“微软Office365”),近一段时间来在内容创作上面有一些新的突破——推出了一个关于探讨大脑及思维运作的专题。请…

2019-03-11-算法-进化(求众数)

题目描述 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在众数。 示例 1: 输入: [3,2,3] 输出: 3示例 2: 输入: [2,2,1,1,1,2,2] 输出: 2思路&#xff1a…

淘宝商品数据库设计的一些经验

前言这几个月都在做一个通过淘宝API线下管理淘宝店的系统,学习了很多东西,这里想对淘宝商品表设计用自己的想法表现出来,如果你觉得很扯淡,可以写下自己的看法.OK,切入正题.淘宝的商品这块的复杂程度,是我见…

2019-03-11-算法-进化(搜索二维矩阵II)

题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性: 每行的元素从左到右升序排列每列的元素从上到下升序排列 示例: 现有矩阵 matrix 如下: [[1, 4, 7, 11, 15],[2, 5, 8, 12, 19],[3, 6, 9…

A and B and Lecture Rooms

A and B and Lecture Rooms 题意要求我们找有多少个点iii满足dis(i,x),dis(i,y)dis(i, x), dis(i, y)dis(i,x),dis(i,y),输出点iii的数量即可。 首先特判无解的情况就是dis(x,y)dis(x, y)dis(x,y)为奇数时,接下来我们讨论有解的情况,大致分…

DevOps之持续集成SonarQube代码质量扫描

SonarQube是一个用于代码质量检测管理的开放平台,可以集成不同的检测工具,代码分析工具,以及持续集成工具。SonarQube 并不是简单地把不同的代码检查工具结果直接显示在 Web 页面上,而是通过不同的插件对这些结果进行再加工处理&a…