第2章 NIO入门
2.1 传统的BIO编程
以服务器为例,在传统BIO模型下的服务器,每当一个新的请求到来的时候回分配一个线程去处理该请求,并且该线程在执行IO操作的时候会一直阻塞,知道IO操作完成或抛出异常才会返回。当网络情况不佳时,网络IO可能会耗费大量时间,那么就会同时有大量线程在服务器上阻塞着,很容易造成内存溢出。
这种模型被称为同步阻塞模型,同步指的是只有等待线程IO操作完成该线程才会返回,阻塞指的是IO没有完成的时候一直等待。
2.1.1 服务端代码
Server类,监听8080端口,在while循环里Server端阻塞在server.accept上,即等待请求传到8080端口上,从accept方法返回。后续new Thread是新建一个线程去处理请求。
public class TimeServer {
public static void main(String[] args) throws IOException {
int port = 8080;
ServerSocket server = null; try {
server = new ServerSocket(port);
System.out.println("The server start in port "+port);
Socket socket = null;
while (true){
socket = server.accept();
Thread thread = new Thread(new TimeServerHandler(socket));
thread.start();
} } catch (IOException e) {
e.printStackTrace();
} finally {
if (server!=null){
System.out.println("Time server close");
server.close();
server=null;
}
}
}
}
执行代码用jstack打印线程状态,看到server线程在17行“停止”,即阻塞在17行等待请求传过来。这种阻塞就是BIO里的B,block,一个IO没有完成就一直卡在那里。
有新的客户端接入新建线程执行处理方法,通过检查传过来的字符串是否是要求的“QUERY TIME ORDER”,如果是就返回当前服务器的时间,否则返回错误信息。
public class TimeServerHandler implements Runnable {
private Socket socket; public TimeServerHandler(Socket socket) {
this.socket = socket;
} public void run() {
BufferedReader in = null;
PrintWriter out = null; try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
String currentTime = null;
String body = null;
while (true){
body = in.readLine();
if (body == null){
break;
}
System.out.println("The time server receive order: "+body);
currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body)?new Date(System.currentTimeMillis()).toString():"BAD ORDER";
out.println(currentTime);
}
} catch (IOException e) {
e.printStackTrace();
if (in!=null){
try {
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
if (out!=null){
out.close();
out = null;
} if (socket!=null){
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}finally {
socket=null;
}
}
}
}
}
同时开启服务端和客户端后可以在控制台看到输出。
2.1.2 缺点
- 每个请求都需要一个新建线程去处理,扛不住太大的并发,因为没有给线程数目设置瓶颈。
- BIO会在网络不佳情况导致大量线程。
2.2 伪异步IO编程
2.2.1 代码
用线程池代替不停的新建线程,好处是线程池是有界的,避免在极端情况下不停新建线程。
public class TimeServer_ThreadPool {
public static void main(String[] args) {
int port = 8080;
ServerSocket server = null;
try {
server = new ServerSocket(port);
System.out.println("server start at port "+ port);
Socket socket = null;
ExecutorService pool = Executors.newFixedThreadPool(10);
while (true){
socket = server.accept();
pool.execute(new TimeServerHandler(socket));
} } catch (IOException e) {
e.printStackTrace();
}
}
}
2.2.2 弊端
- 使用BIO读取数据时,线程会一直阻塞直到 1、有数据读 2、数据读取完毕 3、抛出异常。当客户端请求发送较慢或者网络时延较时,读取数据的线程会一直阻塞。
- 使用BIO输出数据时,线程会一直阻塞直到 1、有数据写 2、数据写完 3、抛出异常。当服务端写数据时,如果网络情况不佳,客户端不能及时读取数据,大量数据留在TCP缓冲区,当发送端即服务端的Window size为0的时候写线程就会无法继续写从而阻塞。
- 无论读还是写,都是阻塞的,阻塞与否以及阻塞是否严重依赖于网络传输的质量。
- 当线程池的队列使用阻塞队列时,前台线程负责把请求封装成对象加入线程池的阻塞队列,如果网络状况十分的差,阻塞队列也满了,那么复制把请求对象加入阻塞队列的前台线程也会阻塞,整个系统失去异步性,所有的请求都会超时。
2.3 NIO 编程
NIO与BIO的区别在两点
- 面向的对象不同。BIO面向Stream,该Stream是单向通信,只能是读Stream或者写Stream。NIO面向Buffer,NIO面向buffer和channel,channel是铁路,buffer是铁路上运输的数据。
- 阻塞性。BIO是阻塞的,NIO通过Selector实现多路复用。
2.3.1 Buffer与Channel
第2章 NIO入门的更多相关文章
- 第二章 NIO入门
传统的同步阻塞式I/O编程 基于NIO的非阻塞编程 基于NIO2.0的异步非阻塞(AIO)编程 为什么要使用NIO编程 为什么选择Netty 第二章 NIO 入门 2.1 传统的BIO编程 2.1.1 ...
- (基础篇 走进javaNIO)第二章-NIO入门
在本章巾,我们会分别对 JDK 的BIO ,NIO 和JDK 1.7 最新提供的 NI02.0的使用进行详细说明 ,通过流程图和代 码讲解,让大 家体会到随着 Ja va 1/0 类库的 不断发展和改 ...
- 第1章Java入门体验
第1章Java入门体验 1.java简介和平台应用 Java是sun公司开发出来,现在属于ORACLE公司java分为几个部分:首先是最基础的Java SE部分,这部分是Java的基础知识,主要包括: ...
- 第三章 Docker 入门
第三章 docker 入门 3.1 确保docker已经就绪 首先查看docker程序是否存在,功能是否正常 [#3#cloudsoar@cloudsoar-virtual-machine ~]$su ...
- Java NIO入门(二):缓冲区内部细节
Java NIO 入门(二)缓冲区内部细节 概述 本文将介绍 NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor). 状态变量是前一文中提到的"内部统计机制"的 ...
- Java NIO入门
NIO入门 前段时间在公司里处理一些大的数据,并对其进行分词.提取关键字等.虽说任务基本完成了(效果也不是特别好),对于Java还没入门的我来说前前后后花了2周的时间,我自己也是醉了.当然也有涉及到机 ...
- 第二章 MySQL入门篇
第一章 MySQL入门篇 一.MySql简介 简言: 和SQL Server数据库相同,MySQl也是一个关系型数据库管理系统.由瑞典的MySQL AB公司开发,2008年被SUN公司收购,2009年 ...
- Kettle解决方案: 第一章ETL入门
第一章ETL入门 1.1 OLPT和数据仓库对比 普通的事务系统和商业智能系统(BI)有什么区别? 1个独立的普通事务系统也被称为在线事务处理系统(OLTP) 商业智能系统也常被称为决策支持系统(DS ...
- 学习Zookeeper之第1章Zookeeper入门
第 1 章 Zookeeper入门 1.1 概述 1.2 特点 1.3 数据结构 1.4 应用场景 统一命名服务 统一配置管理 统一集群管理 服务器动态上下线 软负载均衡 1.5 下载地址 第 1 章 ...
随机推荐
- Linux测试硬盘读性能的常用工具-hdparm
通常情况下可以使用fdisk.df等命令查看硬盘的分区情况以及当前已使用空间大小.剩余空间大小等信息.但是如果要查看硬盘的硬件信息如 硬盘型号.序列号.已运行时间等信息该用什么工具查看呢? 在Linu ...
- 在input内添加小图标或文字(元/月)等
文字: <td class="formValue"> <div class="input-group"> <input id=&q ...
- SQL Server DATEADD() 当前时间减7小时
- Looper: Looper,Handler,MessageQueue三者之间的联系
在Android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作.为了达到这个目的Android设计了handler Looper这个系统框架,And ...
- wrod: 突然无法输入汉字
“文件”-“选项”-“高级”-“去掉 输入法控制处于活动状态复选框”.
- AI项目(CV方向)研发流程
- QML随机颜色
color=Qt.rgba(Math.random(),Math.random(),Math.random(),1)
- PAT 甲级 1067 Sort with Swap(0, i) (25 分)(贪心,思维题)*
1067 Sort with Swap(0, i) (25 分) Given any permutation of the numbers {0, 1, 2,..., N−1}, it is ea ...
- lombok插件/slf4j中字符串格式化
大家在编写springboot项目的过程中可能会接触到lombok这个插件,这个插件可以在编译时帮我生成很多代码. 1.@Data生成Getter和Setter代码,用于类名注释 2.@Getter ...
- 看烦了VS2012的黑白调调了吗?换
VS2012的默认深色主题的确让整个IDE看起来很有气场,而且深色的主题保护眼睛,还是蛮不错的.但是看久了也会烦啊.虽然说重要的不是IDE看起来怎么样,而是写出来的代码质量怎么样,但一个好的环境也是会 ...