Java中的NIO非阻塞编程

在JDK1.4以前,Java的IO操作集中在java.io这个包中,是基于流的阻塞API。对于大多数应用来说,这样的API使用很方便,然而,一些对性能要求较高的应用,尤其是服务端应用,往往需要一个更为有效的方式来处理IO。从JDK1.5开始,NIO API作为一个基于缓存区,并能提供非阻塞IO操作的API被引入。 
NIO所在的包为java.nio,其中的n表示non-blocking。但实际上我们可以把它理解为nio=new+io,因为NIO包实现了网络通信和I/O的联合功能,并将它们的结合发挥到极致,实现完美的网络非阻塞通信功能。 
NIO结构图

  • NIO引入:分析普通Socket通信中存在的I/O问题——阻塞通信,并分析传统的解决方法——线程池的优缺点,进而引入NIO解决方案: 
    ①基于Socket通信存在的问题:I/O阻塞通信。 
    在介绍NIO之前,先了解传统I/O操作的方式。以网络应用为例,下图描述了一个典型的网络服务器结构的通信过程: 
    传统网络IO操作过程 
    椭圆形内的操作会循环进行,并且监听连接、读取数据、写入数据的操作都是阻塞的。在ServerSocket类的生存期中,其重要功能如下:

  • 首先创建ServerSocket:

    //启动服务端:ServerSocket server= new ServerSocket(12345);
  • 然后接受新的连接请求:
//监听客户端while(true){Socket socket = server.accept();   //阻塞监听}

对accept()的调用将一直阻塞,直到ServerSocket接受到一个连接请求为止。一旦请求连接被接受,服务器可以读取客户Socket中的输入/输出数据,在读取调用时也会阻塞。下面的代码演示了这个过程:

//输入输出流
BufferReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter os = new PrintWriter(socket.getOutputStream());
//读取数据
String line;//垃圾字符串
while((line=is.readLine())!=null){//读阻塞//回复数据os.println(line);//写阻塞os.flush();
}

在监听的位置accept()会被阻塞,并且在读写客户端数据时也会阻塞。因此这样的操作共造成了3个问题: 
a、accept()方法的调用将造成阻塞,直到ServerSocket接受到一个连接请求位置; 
b、BufferedReader类的readLine()方法在其缓存区未满时将会造成线程阻塞,只有数据足够填满缓存区或者客户端关闭了套接字时,方法才会返回。 

c、产生大量的String垃圾,BufferedReader创建了缓存区从客户套接字读入数据,但是同样创建了一些字符串存储这些数据。虽然BufferedReader内部提供了StringBuffer处理,但是所有的String很快变成了垃圾需要回收,同样的问题在发送消息代码中也存在。 
其中第一个问题是ServerSocket造成的阻塞,第二个问题是BufferedReader缓存造成的阻塞,第三个问题是String造成的垃圾。因此,以上的问题是Java I/O和Java网络通信共同造成的。 
②传统的解决方法:使用线程池。 
在JDK 1.4之前,自由使用线程池是处理阻塞问题最典型的办法。面对大量的客户端的请求,需要使用大量的线程,这时一般是实现一个线程池来处理请求,如图: 
线程池方式处理 
使用线程池的方法是:在服务端启动时创建线程池,当监听到客户端连接时,就为客户端创建一个线程,并将该线程放入线程池中即可。这样在该客户断开连接时,该客户端的处理线程就会被归还到线程池中,以提高线程的池化管理,提高线程的使用效率。实例代码如下:

public class TestThreadPool{public static void main(String args[]){boolean flag = true;try{//创建线程池ExecutorService pool = Executors.newFixedThreadPool(10);//启动服务器ServerSocket server = new ServerSocket(12345);System.out.println("开始监听");while(true){//接受客户端连接Socket socket = server.accept();//为客户端创建一个独立线程pool.execute(new ServiceThread(socket));}//关闭server.close();pool.shutdown();}catch(IoException e){e.printStackTrace();}}
}

线程池使服务器可以处理多个连接,但是它们也同样引发了许多问题。每个线程拥有自己的栈空间并且占用一些CPU时间,耗费很大,而且很多时间是浪费在阻塞的IO操作上,没有有效利用CPU。 
③最新的解决方案:NIO非阻塞通信。 
从上面的分析可以看出,采用线程池的解决方法也会产生它自己的问题——线程开销,线程开销同时也影响性能和可伸缩性。不过,随着NIO的到来,一切都改变了。 
NIO的非阻塞IO机制是围绕选择器和通道构建的。Channel类表示服务器和客户机直接的一种通信机制。与反应器模式一致,Selector类是Channel的多路复用器。Selector类将传入客户机请求多路分用,并将它们分派到各自的请求处理程序,实现对客户端请求事件的非阻塞监听,如下图: 
NIO通信过程 
在椭圆形区域中,Selector监听器负责轮循客户端的连接、读取和写入事件,这些事件的执行都不会被阻塞。并且为了提高执行的效率,NIO在读取和写入的数据中使用了缓存区。

转发:https://blog.csdn.net/luliuliu1234/article/details/61914097

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423438.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nginx----基础

静态资源服务 通过本地文件系统提供服务:对css,js文件,图片等静态文件 反向代理服务 缓存:将一些数据经常不变的,缓存到Nginx中,直接给用户提供服务 负载均衡 api服务 OpenResty 数据库的服务比较简单&…

c#开发IE控件

c#开发IE控件主要是对BHO对象是使用,但是我们知道BHO是一个COM对象,而在.NET下开发基于COM的应用,总觉得不是很简单,这里有受控代码与COM的调用,我查找了下,国内并没有此类信息,下面是译稿,翻译的不好,欢迎指出.介绍:我们在浏览Internet信息的时候,往往需要增强用户浏览信息的,…

JVM直接内存

概述 直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native…

英语----专业单词

directive (滴 ‘ruai k tive) n:指令determine 【di tε:min】 (de ter min) v:确定 词根:term 边界 distributions (dis tree biu tion)v:分配 C:发行版 exact (衣 ge za k t) adj:确切的 ex&#xff1a…

js遍历table

js遍历table var tableObj document.getElementById("tableName");var str "";for(var i0;i<tableObj.rows.length;i){for(varj0;j<tableObj.rows[i].cells.length;j){//str tableObj.rows[i].cells[j].innerHTML" ";for(var z0;z<…

深入理解JVM—JVM内存模型

我们知道&#xff0c;计算机CPU和内存的交互是最频繁的&#xff0c;内存是我们的高速缓存区&#xff0c;用户磁盘和CPU的交互&#xff0c;而CPU运转速度越来越快&#xff0c;磁盘远远跟不上CPU的读写速度&#xff0c;才设计了内存&#xff0c;用户缓冲用户IO等待导致CPU的等待成…

Nginx----进阶

用Nginx搭建一个静态的web资源服务器/动静分离 简单使用 1、可以在安装的nginx目录新建自己的目录zy&#xff08;和conf在一个目录下&#xff0c;也就是和html目录在一个目录下&#xff0c;注意如果使用/zy&#xff0c;那么zy目录需要创建在linux根目录&#xff09;&#xff0c…

ASP.NET页面生命周期描述

ASP.NET页面生命周期描述2008-09-12 09:25在以前写个一篇关于ASP.NET页面生命周期的草稿,最近又看了看ASP.NET&#xff0c;做个补充,看看页面初始过程到底是怎么样的 下面是ASP.NET页面初始的过程: 1. Page_Init(); 2. Load ViewState; 3. Load Postback data; 4. Page_Load();…

小程序·云开发的HTTP API调用丨实战

小程序云开发之httpApi调用。 小程序云开发之httpApi调用&#xff08;返回“47001处理”&#xff09; 技术栈 采用 nodejs express 搭建web服务器&#xff0c;采用 axios 请求第三方 httpApi nodejsexpressaxios 项目结构 通过应用生成器工具 express-generator 可以快速创建一…

Java hashCode() 和 equals()使用的场景

第3部分 hashCode() 的作用 hashCode() 的作用是获取哈希码&#xff0c;也称为散列码&#xff1b;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。 hashCode() 定义在JDK的Object.java中&#xff0c;这就意味着Java中的任何类都包含有hashCo…

坚守基本的职业信仰

深陷公司的政治斗争会让任何当事人都疲于奔命&#xff0c;尤其是当这种斗争的双方都是您的上级。除非您一开始就能够知道最终的斗争结果&#xff0c;否则任何具有倾向性的言行都会给自己带来难堪。 深陷入别人的职业斗争是一个职业经理人职业生涯最大的不幸&#xff0c;除非…

Zookeeper----基本原理

Zookeeper作用是什么&#xff1f; 协调分布式系统中的多个服务器&#xff0c;使得系统可以正常工作。 Zookeeper提供了什么&#xff1f; 实际上他只提供了三个东西&#xff0c;一个是文件系统&#xff0c;一个是通知机制&#xff0c;还有一个是集群管理机制 Zookeeper可以做什么…

Java 中 Comparable 和 Comparator 比较

Comparable 简介 Comparable 是排序接口。 若一个类实现了Comparable接口&#xff0c;就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序&#xff0c;假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”&#xff0c;则该List列表(或数组)可以通…

spgridview的过滤功能回调时发生错误~

代码中启用了过滤功能&#xff0c; 但当点击过滤的列时发生错误&#xff1a; error: spgridview_filtercallbackerrorhandler() was called - result 回调时发生错误... 详细见&#xff1a; HTML代码&#xff1a; AllowFiltering"True"FilterDataFields",Name,,…

web---SSL/TSL

对称加密 加密算法秘钥&#xff08;双方持有相同的秘钥&#xff09;&#xff0c;A使用加密算法秘钥加密文件&#xff0c;B使用加密算法秘钥解密文件&#xff1b; 演示一个对称加密RC4算法 注意&#xff1a;RC4加密是有漏洞的 明文和秘钥进行异或得到密文&#xff0c;密文和秘钥…

讨论了好久的问题,IE、Firefox下CSS图片垂直居中的问题

通过百度和谷歌找了好久都没找着一个合适的方法。以下是自己找出的一种方法&#xff0c;自认为还可以&#xff0c;而且&#xff0c;也方便简单。IE:当容器为div,或者tr,只要把容器的Css属性line-height设置成容器的高度就行了.当容器为a,且容器的css属性display为inline-block或…

Nginx----实现https站点

1、首先给域名设置证书&#xff0c;可以去阿里云购买 1、下载自动化脚本 目的&#xff1a;帮我们自动在nginx配置中添加证书 yum install python2-certbot-nginx2、输入命令 certbot --nginx --nginx-server-root/usr/local/openresty/nginx/conf/ -d zy.com 选择我们的url请求…

TCP/IP四层模型和OSI七层模型的概念

TCP/IP四层模型 TCP/IP是一组协议的代名词&#xff0c;它还包括许多协议&#xff0c;组成了TCP/IP协议簇。TCP/IP协议簇分为四层&#xff0c;IP位于协议簇的第二层(对应OSI的第三层)&#xff0c;TCP位于协议簇的第三层(对应OSI的第四层)。 TCP/IP通讯协议采用了4层的层级结构&…

setsockopt()用法(转载)

1. 如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分&#xff09;调用 closesocket&#xff08;一般不会立即关闭而经历TIME_WAIT的过程&#xff09;后想继续重用该socket&#xff1a; BOOL bReuseaddrTRUE; setsockopt(s,SOL_SOCKET ,…

Nginx----OpenResty

概要 OpenResty是一个基于Nginx与Lua的高性能Web平台&#xff0c;其内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态Web应用、Web服务和动态网关。OpenRestye通过汇聚各种设计精良的Nginx模块&#xff08;主要由O…