文档章节

Java中的阻塞和非阻塞IO包各自的优劣思考

longload
 longload
发布于 2016/07/12 17:49
字数 1255
阅读 3
收藏 0

转载地址:http://javag.iteye.com/blog/221641

 

NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。

反应器(Reactor):用于事件多路分离和分派的体系结构模式

通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞非阻塞 。所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待 状态, 直到有东西可读或者可写为止。而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待

 

一种常用做法是:每建立一个Socket连接时,同时创 建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但 是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况。

另一种较高效的做法是:服务器端保存一个Socket连 接列表,然后对这个列表进行轮询,如果发现某个Socket端口上有数据可读时(读就绪),则调用该socket连接的相应读操作;如果发现某个 Socket端口上有数据可写时(写就绪),则调用该socket连接的相应写操作;如果某个端口的Socket连接已经中断,则调用相应的析构方法关闭 该端口。这样能充分利用服务器资源,效率得到了很大提高。

 

传统的阻塞式IO,每个连接必须要开一个线程来处理,并且没处理完线程不能退出。

非阻塞式IO,由于基于反应器模式,用于事件多路分离和分派的体系结构模式,所以可以利用线程池来处理。事件来了就处理,处理完了就把线程归还。而传统阻塞方式不能使用线程池来处理,假设当前有10000个连接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就需要开10000个来处理。如果连接数较多将会出现资源不足的情况。非阻塞的核心优势就在这里。

为什么会这样,下面就对他们做进一步细致具体的分析:

首先,我们来分析传统阻塞式IO的瓶颈在哪里。在连接数不多的情况下,传统IO编写容易方便使用。但是随着连接数的增多,问题传统IO就不行了。因为前面说过,传统IO处理每个连接都要消耗 一个线程,而程序的效率当线程数不多时是随着线程数的增加而增加,但是到一定的数量之后,是随着线程数的增加而减少。这里我们得出结论,传统阻塞式IO的瓶颈在于不能处理过多的连接。

然后,非阻塞式IO的出现的目的就是为了解决这个瓶颈。而非阻塞式IO是怎么实现的呢?非阻塞IO处理连接的线程数和连接数没有联系,也就是说处理10000个连接非阻塞IO不需要10000个线程,你可以用1000个也可以用2000个线程来处理。因为非阻塞IO处理连接是异步的。当某个连接发送请求到服务器,服务器把这个连接请求当作一个请求"事件",并把这个"事件"分配给相应的函数处理。我们可以把这个处理函数放到线程中去执行,执行完就把线程归还。这样一个线程就可以异步的处理多个事件。而阻塞式IO的线程的大部分时间都浪费在等待请求上了。

 

java NIO常出现的问题:

注册的事件没有及时注销,导致不停的触发.然后cpu100%.

1.读事件没有注销:当客户端关闭连接的时候,channel.read(buf) 的时候返回<=0的值,并且会不停触发读事件.这个时候如果没有把当前事件cancel掉,则会出问题.这里很容易同多次读包混淆在一起,当客户端断开时,除了read其它地方都不能判断出客户端已经断开.

2.写事件没有及时注销:当事件可以写完后,要立即把关注写事件给关掉,不然当网卡IO可写的时候就会触发事件.

© 著作权归作者所有

上一篇: java23种设计模式
下一篇: shrio学习
longload
粉丝 3
博文 66
码字总数 104702
作品 0
成都
程序员
私信 提问
tomcat-tomcat bio nio apr 模式性能测试与个人看法

11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态、那后来主管就要求调优了,下面是tomcat bio、nio、apr模式以及后来自己测试的一些性能结果。 原理方面的资料都是从网上找...

抢地主
2017/11/04
0
0
Linux IO模型与Java NIO

概述 看Java NIO一篇文章的时候又看到了“异步非阻塞”这个概念,一直处于似懂非懂的状态,想解释下到底什么是异步 什么是非阻塞,感觉抓不住重点。决定仔细研究一下。 本文试图研究以下问题...

yingtju
2018/06/29
0
0
Tomcat的BIO、NIO、APR模式对比与性能测试结果

11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态、那后来就要求调优了,下面是tomcat bio、nio、apr模式以及后来自己测试的一些性能结果。 原理方面的资料都是从网上找的,...

DemonsI
02/15
0
0
Java核心(五)深入理解BIO、NIO、AIO

导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别;BIO、NIO、AIO 的区别;理解和实现 NIO 操作 Socket 时的多路复用;同时掌握 IO 最底层最核心的操作技巧。 BIO、NIO、AIO 的区别是什...

王磊的博客
2018/12/03
0
0
IO的阻塞与非阻塞、同步与异步以及Java网络IO交互方式

最近工作中,接触到了Java网络编程方面的东西:Socket、NIO、MongoDB等,也看了tomcat的源码,也加强了线程方面的知识,也使用了MINA这样的框架。感觉获益良多,原本技术上的薄弱环节也在慢慢...

毛爷爷夸我帅
2015/03/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java中print、printf、println的区别

printf主要是继承了C语言的printf的一些特性,可以进行格式化输出 print就是一般的标准输出,但是不换行 println和print基本没什么差别,就是最后会换行

hellation_
27分钟前
0
0
spring在静态类中注入bean的的解释

@Componentpublic class ModelMapper {@AutoWiredprivate static AssignmentManager assignmentManager;public static void add(){a+b;}} 静态方法是属于类的,普通方法才属于...

无知的小狼
28分钟前
2
0
分而治之-归并排序

如果有1个数组,数组的左半部分和右半部分都已经排好序,如何将该数组合成1个有序的数组? 开辟1个同样大小的临时空间辅助我们完成归并过程,如下图 k:表示归并过程中,当前需要替换的原数组...

万山红遍
42分钟前
2
0
Linux修改时区的正确方法【修改时间,需要修改软连接,靠谱】

CentOS和Ubuntu的时区文件是/etc/localtime,但是在CentOS7以后localtime以及变成了一个链接文件 [root@centos7 ~]# ll /etc/localtime lrwxrwxrwx 1 root root 33 Oct 12 11:01 /etc/loca......

Airship
今天
1
0
《Netkiller Spring Cloud 手札》之 Master / Slave 主从数据库数据源配置

5.19.1. Master / Slave 主从数据库数据源配置 5.19.1.1. application.properties spring.datasource.master.driverClassName = com.mysql.cj.jdbc.Driverspring.datasource.master.url=j......

netkiller-
今天
50
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部