每日一句

人的苦楚会把本人折磨到多深呢?

每日一句

You cannot swim for new horizons until you have courage to lose sight of the shore.
除非有勇气来到岸边,否则你永远游不到此岸。

概念

IO 是主存和外部设备(硬盘、终端和网络等)拷贝数据的过程。IO是操作系统的底层性能实现,底层通过I/O指令进行实现。

以下是5品种Unix下可用的I/O模型

1. 阻塞式I/O:Blocking IO

2. 非阻塞式I/O:nonblocking IO

3. I/O 复用(Select,poll epoll):IO multiplexing

4. 信号驱动式I/O(SIGIO):signal driven IO

5. 异步 I/O(posix 的 aio 系列函数):asynchromous IO

Blocking IO

在 Linux 中,默认状况下所有的 socket 都是 Blocking,一个典型的读操作流程大略是这样:

1. 通常波及期待数据从网络达到。当所有期待数据达到时,它被复制到内核中的某个缓冲区

2. 把数据从内核缓冲区复制到应用程序缓冲区

当用户过程调用了 recvfrom 这个零碎调用, kernel 就开始了 IO 的第一个阶段:筹备数据。对于 network IO 来说,很多时候数据在一开始还没有达到(比方,还没有收到一个残缺的 UDP 包)。这个时候 kernel 就要期待足够的数据到来。而在用户过程这边,整个过程会被阻塞。当 kernel 始终等到数据筹备好了,它就会将数据从kernel 中拷贝到用户内存,而后kernel返回后果,用户过程才解除 block 的状态,从新运行起来。
所以,Blocking IO 的特点就是在IO执行的两个阶段都被 block了

非阻塞式I/O

Linux 下,能够用过设置 socket 使其变为 non-blocking。当对一个 non-blocking socket 执行操作时,流程如下:
从图中能够看出,当用户过程收回read操作时,如果kernel中的数据还没有筹备好,那么它并不会block用户过程,而是立即返回一个error。 从用户过程角度讲 ,它发动一个read操作后,并不需要期待,而是马上就失去了一个后果。用户过程判断后果是一个error时,它就晓得数据还没有筹备好,于是它能够再次 发送read操作。一旦kernel中的数据筹备好了,并且又再次收到了用户过程的system call,那么它马上就将数据拷贝到了用户内存,而后返回。

所以,用户过程第一个阶段不是阻塞的,须要一直的被动询问kernel数据好了没有;第二个阶段仍然总是阻塞的。

IO 多路复用(NIO)

select、epoll 的益处就在于单个 process 就能够同时解决多个网络链接的 IO。

IO 复用和同步阻塞实质一样,不过利用了新的 Select 零碎调用,由内核来负责原本是申请过程该做的轮训操作,看似不非阻塞IO还多了哥零碎调用开销,不过因为反对多路IO才算进步了效率
也就是一个能够监听多个。
它的基本原理就是 select、epoll 这个 function会一直的轮询所负责的所有 socket,当某个 socket 有数据达到了,就告诉用户过程。它的流程如下图:

当用户线程调用select,那么整个过程会被阻塞,而同时,kernel会监督所有select负责的 socket =,当任何一个 socket 中的数据筹备好了,select 就会返回,这个时候用户过程会调用 read 操作,将数据 kernel 拷贝到用户过程。
首先开启套接字的信号驱动式IO性能,并且通过sigaction(信号处理程序) 零碎调用装置一个信号处理函数 ,该函数调用将立刻返回,以后过程没有被阻塞 ,持续工作;当数据报筹备好的时候,内核为该过程产生SIGIO 的信号,随后既能够在信号处理函数中调用recvfrom 读取数据报,并且告诉主循环数据曾经筹备好期待解决;也能够间接告诉主循环让它读取数据报;(其实就是一个待读取的告诉和待处理的告诉),根本不会用到。

异步IO(AIO)

多线程和多过程的模型尽管解决了并发的问题,然而零碎不能有限的减少线程,因为零碎的切换线程的开销恒大,所以,一旦线程数量过多,CPU的工夫就花在线程的切换上,正真运行代码的工夫就会缩小,后果导致性能重大降落

因为咱们要解决的问题是CPU高速执行能力和IO设施的龟速重大不匹配,多线程和多过程只是解决这一个问题的一种办法。
另一种解决IO问题的办法是异步IO,当代码须要执行一个耗时的IO操作时,他只收回IO指令,并不期待IO后果而后就去执行其余代码,一段时间后,当IO返回后果是,在告诉CPU进行解决咱们调用aio_read函数,给内核传递描述符,缓冲区指针,缓冲区大小,和文件偏移量,并且通知内核当整个操作实现时如何告诉咱们,该函数调用后,立刻返回,不会被阻塞

另一方面:从kernel的角度,当他收到一个aio_read之后,首先它立刻返回,所以不会对用户过程产生block,而后kernel会期待数据筹备实现,而后将数据拷贝到用户内存(copy由内核实现),当着所有实现后,kernel会给用户过程发送一个singal或者执行下一个基于线程回调函数来实现此次IO处理过程,通知他read操作实现

美文佳句

岁月应是静好。近来,心神总是不宁,想必是被尘世间的引诱所困。

我想,要是远方的祥夫学生来到我这“梅知堂”,两人清茶一杯,盘腿而坐,或看他画梅,纸上的梅花好像兀自开在飞雪里,如是,那该是一幅怎么的墨梅图?

昨晚,梦里看到那个戴着小黑圆眼镜的祥夫背着黄色的大包正往江南赶路。是又到了梅花开的日子了吗?

面试题

SpringMVC工作原理?

1. 客户端发送申请到前端控制器 DispatcherServlet2. DispatcherServlet 收到申请后,调用 HandlerMapping 处理器映射器,申请获取 handler3. 处理器映射器依据 url 找到具体的处理器,生成处理器对象以及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet4. DispatcherServlet 调用 HandlerAdapter 处理器适配器5. HandlerAdapter 通过适配器调用 具体处理器(Handler,也叫后端控制器)6. Handler 执行实现返回 ModelAndView7. HandlerAdaper 将 Handler 执行后果 ModelAndView 返回给 DispatcherServlet8. DispatcherServlet 将 ModelAndView 传给 ViewResolver 视图解析器 进行解析9. ViewResolver 解析后返回具体 View10. DispatcherServlet 对 view 进行 渲染视图(行将模型数据填充至视图中)11. DispatcherServlet 响应用户

ArrayList 、LinkedList和Vector的区别?

ArrayListLinkedListVector
线程是否平安不保障不保障保障线程平安,然而底层大量应用了synchronized关键字,效率不是很高
底层数据结构数组,查问效率高,多用于查问较多的场合LinkedList 底层是双向链表,插入和删除十分不便,实用于插入较多的场合数组,查问效率高,多用于查问较多的场合
默认大小与扩容JDK 1.7 之前默认大小是 10 JDK 1.7 之后是0 每次依照1.5倍扩容底层是链表构造,是不间断的存储空间,没有默认大小的说法Vector扩容是2倍

@RestController 和 @Controller 有什么区别?

@RestController 注解,在 @Controller 根底上,减少了 @ResponseBody 注解,更加适宜目前前后端拆散的架构下,提供 Restful API ,返回例如 JSON 数据格式。当然,返回什么样的数据格式,依据客户端的 "ACCEPT" 申请头来决定。

你好,我是yltrcc,日常分享技术点滴,欢送关注我:ylcoder