标签:http io 使用 java ar for 文件 sp 问题
事件处理模型, 也即是全异步事件处理模型。在以前, 对于那些同时执行多项任务, 但仍能响应用户交互的应用程序通常需要实施一种使用多进程(如linux的fork操作)或者多线程的操作。对于低并发的环境, 这样做无疑能避免进程因等待某个操作而出现"假死"现象。但对于更复杂的异步应用程序或者是要求高并发的环境, 就要使用事件模型来处理异步事件, 这样做有很多好处:
当然, 基于事件的处理模型也有其缺点:
当前, 基于事件的处理模型被应用到了各种环境之中。譬如linux的epoll模块, javascript语言以及Nginx服务器等。
以下面的javascript代码作为例子来讲解事件处理模型的特点:
<script type="text/javascript">
var callback = function () {
alert(‘Hello world‘);
};
doucment.onclick = callback;
......
</script>
这就是实现事件处理模型的一般模式: 首先定义一个或多个异步事件, 每一个事件绑定回调函数。主进程注册完事件后就继续执行, 只有当事件被触发时才会执行回调函数。放到例子当中就是当用户点击文档时会弹出窗口并显示 Hello world。
综上: 基于事件模型的程序要具备以下结构, 如图:
Event Loop是一个很重要的概念, 指的是计算机系统实现的一种运行方式, 主要用于等待并发送消息和事件。虽然在每一种实现方式中具体的实现方法可能不同(例如Nginx事件模型和javascript事件模型), 但是都需要实现并维护Event Loop。 在计算机中, 每一个运行的程序就叫做进程(process)。 一般情况下, 一个进程只能一次只能执行一个任务。如果想要执行多个任务, 不外乎以下三种解决方式:
以上2和3方式分别对应多进程和多线程模型, 优劣在之前已经讲述。而事件处理模型正是基于上面第一种方式, 这样做可以避免不必要的进程或线程间切换, 保证进程的高效运行。但是有一个问题, 一旦遇到大量任务或者是遇到一个耗时的操作, 进程就会被阻塞, 出现所谓的"假死"现象, 无法响应其他操作。
按照上面的运行模型, 如果某个任务很耗时,那么进程的运行大概是这个样子:
上图的绿色部分是程序运行时间, 红色部分是等待时间。这个进程在大部分时间都在等待其他操作, 这种运行方式称为"同步模式"(synchronous I/O)或"堵塞模式"(blocking I/O)。
如果采用多进程或者多线程, 很可能就是下面这种情况:
上图表明, 比起单进程, 多进程耗费成倍的系统资源并闲置等待, 这显然不合理。
Event Loop就是为了解决单进程阻塞问题而提出来的一种合理方案。以javascript作为例子, 在程序中设置一个主进程和若干个子线程(以1个子线程为例)。主进程负责程序本身的运行并处理"非阻塞"操作; 子线程负责与其他进程(主要是I/O操作等耗时进程)的通信, 这个线程就被称为"Event Loop线程"。
上图橙色表示空闲时间。每当遇到I/O操作等耗时操作时, 主进程就让Event Loop线程去通知相应的I/O程序并注册相应的事件和设置回调函数, 然后主线程接着往后运行, 所以不出现红色的阻塞时间, 等到I/O操作完成, Event Loop线程再把结果返回主进程, 主进程调用实现设定的回调函数完成任务(注意: 回调函数不能执行太多的耗时操作, 因为此时主进程是处于阻塞状态的)。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。这也是事件处理模型的内部实现机制。
在计算机中, 上下文代表着很多种含义。在基于事件的模型中,上下文表示什么?简单的讲, 以javascript为例, 就是在主进程注册事件后将回调函数作用域内的变量保存成一个对象保存起来, 这个对象就叫做上下文对象。每一个事件的回调函数都包含着自己的上下文对象, 当对应事件被调用并执行回调函数时, 函数可以直接通过上下文对象获得作用域内保存变量的值, 这个操作对开发者是透明的, 开发着只需要直接写对象名称就可以了。
在基于事件的模型中, 上下文是必须存在的, 为什么要定义上下文这个概念呢?因为基于事件的模型都是基于异步机制的。以javascript为例, 每次主进程执行到结尾的时候就会释放其作用域内的所有变量。换句话说, 不管事件有没有被触发, 主进程执行完所有的逻辑之后就会销毁所有的变量。如果没有上下文的话, 当用户触发事件执行回调函数时, 就会无法找到其作用域内的变量, 使用上下文就是为了让每一个特定的回调函数能访问到属于自己作用域内的变量的值。
在实现一个基于事件模型的应用的过程中, 有一个问题是必须考虑到的, 那就是主进程究竟要创建多少子线程才比较合理, 也就是说Event Loop什么时候需要创建。如果创建的子线程太多或是太少, 会出现以下问题:
子线程的数目主要要根据应用处理的业务类型, 具体机器的内存和cpu等因素决定, 并没有一致的规定。以下做法是比较好的一种实践:
对于高并发, 多请求的事件, 传统的多线程和多进程的方法已经难以应付这些情况。而基于事件的模型由于采用的是异步的方式, 通过类似于中断上下文的操作, 能获得很好的并发性和高性能。并且能避免之前模型出现的一些棘手问题, 比如死锁问题。随着应用复杂度飞不断提高, 相信会有更多的应用将会采用基于事件的模型来应对这些情况。
标签:http io 使用 java ar for 文件 sp 问题
原文地址:http://www.cnblogs.com/heidsoft/p/3976060.html