您的位置:首页 > 其它

NIO学习(二)

2017-01-22 00:48 218 查看
1.BIO : Blocking-I/O。传统的同步阻塞IO,这就是服务器常用的每连接每线程模型。当有一个连接时就开启一个线程进行处理,但是当请求不做任何操作时就造成浪费,可以采用线程池机制进行改善,减少了系统在管理线程和线程上下文切换的开销。在活动连接数比较少的情况下,这种模型是比较合适的,可以让每一个连接专注于自己的IO并且模型较为简单。不过,这个模型最本质的问题在于,严重依赖于线程。但线程是很”贵”的资源,主要表现在:

(1)线程的创建和销毁成本很高,在Linux这样的操作系统中,线程本质上就是一个进程。创建和销毁都是重量级的系统函数。

(2)线程本身占用较大内存,像Java的线程栈,一般至少分配512K~1M的空间,如果系统中的线程数过千,恐怕整个JVM的内存都会被吃掉一半。

(3)线程的切换成本是很高的。操作系统发生线程切换的时候,需要保留线程的上下文,然后执行系统调用。如果线程数过高,可能执行线程切换的时间甚至会大于线程执行的时间,这时候带来的表现往往是系统load偏高、CPU sy使用率特别高(超过20%以上),导致系统几乎陷入不可用的状态。

(4)容易造成锯齿状的系统负载。因为系统负载是用活动线程数或CPU核心数,一旦线程数量高但外部网络环境不是很稳定,就很容易造成大量请求的结果同时返回,激活大量阻塞线程从而使系统负载压力过大。

所以,当面对十万甚至百万级连接的时候,传统的BIO模型是无能为力的。

2.NIO:Non-Blocking-I/O。同步非阻塞IO,每请求每线程。所有系统的IO都要经历两个阶段:等待就绪和操作。当客户端发送的连接请求注册到多路复用器,多路复用器轮询到右IO请求时才开启一个线程处理请求。NIO的一个重要特点就是:socket主要的读,写,注册,和接收函数在等待就绪阶段是非阻塞的,而真正的IO操作是同步阻塞的。NIO的读写函数都可以立即返回,这就为NIO不使用多线程提供了机会。当一个线程不能进行读写(socket.read()和socket.write()返回值为0时),就把这个线程记录下来(在selector上注册一个标记位),然后线程去执行其他就绪的请求。

3.AIO:Asynchronized-Non-Blocking-I/O。异步非阻塞IO。

4.多路分离器

IO读写时,IO复用机制都会依赖多路分离器(负责把源事件的IO分发到对应的事件分离器)。开发人员在开始的时候再事件分离器那里注册感兴趣的事件,并提供相应的处理者或者回调函数。

Reactor(同步IO):当接收到一个事件请求时,先传递给事先注册的处理函数或者回调函数,由后者进行读写操作。

Proactor(异步IO):直接发起异步读写操作,实际是由操作系统完成。

感谢这篇文章的参考:Java NIO浅析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程池 线程 NIO