`
javaG
  • 浏览: 554657 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

    博客分类:
  • java
阅读更多

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可写的时候就会触发事件.

 

 

分享到:
评论
5 楼 猪的暧昧 2013-01-21  
4 楼 JasonShieh 2011-04-11  
javaG 写道
taoeaten 写道
谢谢博主啊~这个主题在java网络编程中的解释着实不如博主的解释,不过
“而传统阻塞方式不能使用线程池来处理,假设当前有10000个连接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就需要开10000个来处理”能不能解释下,传统阻塞方式为什么不能用线程池来处理啊?呵呵~

其实就算你用了线程池,假设线程池的大小是500.这时候同时过来1000个请求,一般来说如果这1000个请求都很快的被处理了,可能当前线程池也就30-50个线程在跑过着更低,但是如果当这1000个请求由于网络原因不能很快的被处理,假设每个线程处理一个需要2秒钟,那末你线程池的500个线程段时间内就全部被耗干净了.因为同步模式在处理同意连接时,一般的过程是接收->处理->返回,这个过程任何一个地方出问题这个线程都会被占用.而异步的是 判断接收是否ok?(处理->返回是否ok?返回:把结果丢到队列里面,处理下一个请求):处理下一个请求(这样就可以立即释放没有ok的请求,减少cpu空耗时间和线程池线程耗尽的问题) 注意理解里面的区别.

也就是说,传统的阻塞I/O也可以用线程池。而且我觉得很有价值啊,理论上好像可以增加线程的重复利用率。而非阻塞好像都没有必要用线程池。因为感觉很少的线程就可以实现并发事件了。不知道我理解的对不对,望楼主释疑。
3 楼 xuehan_1010 2010-09-25  
你应该说是“非阻塞+线程池”
2 楼 javaG 2009-12-16  
taoeaten 写道
谢谢博主啊~这个主题在java网络编程中的解释着实不如博主的解释,不过
“而传统阻塞方式不能使用线程池来处理,假设当前有10000个连接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就需要开10000个来处理”能不能解释下,传统阻塞方式为什么不能用线程池来处理啊?呵呵~

其实就算你用了线程池,假设线程池的大小是500.这时候同时过来1000个请求,一般来说如果这1000个请求都很快的被处理了,可能当前线程池也就30-50个线程在跑过着更低,但是如果当这1000个请求由于网络原因不能很快的被处理,假设每个线程处理一个需要2秒钟,那末你线程池的500个线程段时间内就全部被耗干净了.因为同步模式在处理同意连接时,一般的过程是接收->处理->返回,这个过程任何一个地方出问题这个线程都会被占用.而异步的是 判断接收是否ok?(处理->返回是否ok?返回:把结果丢到队列里面,处理下一个请求):处理下一个请求(这样就可以立即释放没有ok的请求,减少cpu空耗时间和线程池线程耗尽的问题) 注意理解里面的区别.
1 楼 taoeaten 2009-12-04  
谢谢博主啊~这个主题在java网络编程中的解释着实不如博主的解释,不过
“而传统阻塞方式不能使用线程池来处理,假设当前有10000个连接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就需要开10000个来处理”能不能解释下,传统阻塞方式为什么不能用线程池来处理啊?呵呵~

相关推荐

    一文彻底理解Java中IO的BIO、NIO、AIO

    NIO(非阻塞IO)** 为了解决BIO在高并发下的问题,Java推出了NIO模型。NIO的核心在于通道(Channel)和缓冲区(Buffer)。在NIO中,读写操作不再会阻塞,而是变为可选择性阻塞。当数据未准备好时,操作系统不会...

    Java NIO与IO性能对比分析.zip

    Java NIO(New IO)和IO是Java平台中用于处理输入/输出操作的两种主要机制。它们在处理I/O任务时有不同的方式和特点,适用于不同的场景。本篇将深入探讨Java NIO与IO的性能对比,帮助开发者更好地理解两者之间的差异...

    18302010012_王栋辉_Java、JavaScript和C++对异步IO的实现方法及其效率1

    总结来说,Java、JavaScript和C++各自通过不同的方式实现了异步I/O,它们在效率上各有优劣,具体取决于应用场景和编程需求。理解这些语言的异步I/O机制,有助于开发者选择最适合的工具来优化他们的系统程序设计。

    基于Java的实例源码-异步IO框架 Cindy.zip

    2. **非阻塞I/O**:Cindy框架利用Java NIO的非阻塞特性,当数据未准备好时,调用不会阻塞线程,而是立即返回。这使得单个线程可以同时处理多个请求,提高了系统资源的利用率。 3. **Cindy框架特性**: - **事件...

    java的一些常用方法及架包版本1.0

    - `java.nio.*`:非阻塞I/O,性能优于传统`java.io.*`。 - `java.sql.*`:处理数据库连接和SQL操作。 - `javax.swing.*`:用于创建图形用户界面。 9. **版本管理**: - Java有多个版本,如Java 8, 11, 17等,每...

    java常用工具类——个人总结

    - `java.nio` 包中的非阻塞I/O模型,如`Selector`、`Channel`、`Buffer`,提供了更高的并发性能。 8. **线程工具类**: - `java.util.concurrent` 包提供了丰富的并发工具,如`ExecutorService`、`Future`、`...

    JAVA核心知识点整理.pdf

    阻塞IO模型、非阻塞IO模型、多路复用IO模型、信号驱动IO模型和异步IO模型是不同的I/O处理方式,它们在资源使用、性能表现上各有优劣。NIO的缓冲区、非阻塞操作、通道(Channel)和选择器(Selector)是NIO的核心组件...

    JAVA网络通信系统的研究与开发(源代码++开题报告).rar

    5. **NIO(非阻塞I/O)**:Java NIO(New IO)提供了一种不同于传统阻塞I/O的模型,它允许多个通道在单个线程中并发操作,提高了网络通信的效率。 6. **TCP和UDP协议**:TCP(传输控制协议)提供面向连接的、可靠的...

    java深度入险

    另外,Java的IO和NIO(非阻塞I/O)系统提供了丰富的文件操作和网络通信功能,满足各种输入输出需求。 Java虚拟机(JVM)是Java程序运行的平台,它的内存模型(堆、栈、方法区等)和垃圾回收机制对性能优化至关重要...

    Java/JSP获得客户端网卡MAC地址的三种方法解析

    ### 方法一:通过Java NIO(非阻塞I/O)库 Java NIO库提供了访问底层网络接口的能力,从而可以获取包括MAC地址在内的网络接口信息。以下是一种典型的实现方式: ```java import java.net.InetAddress; import java...

    MLDN的JAVA笔记大全

    - **IO与NIO**:JAVA的输入输出库提供了丰富的功能,而NIO(非阻塞I/O)提高了处理大量并发连接的能力。 - **网络编程**:Socket编程和URL类,用于构建客户端和服务器应用。 9. **JVM与性能优化** - **JVM内存...

    JDK_API_1_6_zh_CN.zip

    NIO(New IO)在1.4版本引入,1.6中进一步完善,提供非阻塞I/O和选择器,提高了高并发环境下的性能。 五、网络编程 Java API 1.6在网络编程方面提供了Socket和ServerSocket类,支持TCP/IP通信。HttpURLConnection和...

    125条常见的java面试笔试题汇总

    - **NIO(New IO)**:非阻塞I/O,通道(Channel)和缓冲区(Buffer)的使用。 8. **网络编程** - **Socket编程**:TCP和UDP的基本原理,建立连接、发送和接收数据。 - **HTTP协议**:理解HTTP请求和响应的格式...

    Java编程性能优化技巧有哪些共7页.pdf.zip

    这份名为"Java编程性能优化技巧有哪些共7页.pdf.zip"的压缩文件很可能包含了关于Java性能优化的精华内容,尽管实际的文件列表中仅提及了"赚钱项目",但我们可以通过对Java性能优化的一般性理解和实践来探讨相关知识...

    互联网大厂Java面试题合集

    - **NIO特点**:非阻塞I/O模型,使用通道和缓冲区进行数据传输。 ##### 4.2.1 Java反射原理 - **反射原理**:通过Class对象获取类的信息,创建实例、调用方法等。 - **创建实例方式**:使用Class对象的newInstance...

    服务端源码.rar

    3. Node.js:基于JavaScript的服务器端环境,利用异步I/O实现高效的非阻塞IO操作,适合构建高性能的实时应用。 4. Go:Google推出的Go语言,以其轻量级线程(goroutine)、高效性能和简单的语法,在微服务和高并发...

    WEB服务器工作机制由浅至深(2):【How Tomcat Works】1~4章翻译分析

    Tomcat支持两种并发模型:基于线程的模型和基于NIO(非阻塞I/O)的模型。基于线程的模型中,每个请求都会分配一个线程,而NIO模型使用较少的线程来处理更多的连接,降低了线程创建和销毁的开销。这两种模型各有优劣...

    程序员面试宝典大全,大全

    - **NIO**:掌握非阻塞IO模型,包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。 6. **反射与注解** - **反射**:理解如何通过反射获取类信息、创建对象、调用方法和访问字段。 - **注解**:掌握...

    每日测试:每日测试

    此外,Java的IO流和NIO(非阻塞I/O)系统提供了读写文件和网络通信的能力。 线程是Java并发编程的关键,通过Thread类或Runnable接口可以创建并执行多线程。线程同步机制,如synchronized关键字、volatile变量、wait...

    性能实验室任务

    8. **IO与NIO**:Java的原始IO模型和NIO(非阻塞IO)模型各有优劣,理解两者的工作机制并根据场景选择合适的方式,能够有效提升I/O操作的性能。 9. **并行流与并发容器**:Java 8引入的并行流和并发集合如`...

Global site tag (gtag.js) - Google Analytics