第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 章 ...
随机推荐
- ArcMap与快捷键冲突
ArcMap与快捷键冲突 商务合作,科技咨询,版权转让:向日葵,135-4855__4328,xiexiaokui#qq.com 问题:armap进入鼠标自动导航状态,arcmap失控,系统紊乱,导致 ...
- [转发]ASP.NET Core2集成Office Online Server(OWAS)实现办公文档的在线预览与编辑(支持word\excel\ppt\pdf等格式)
转载自:https://www.cnblogs.com/Andre/p/9549874.html Office Online Server是微软开发的一套基于Office实现在线文档预览编辑的技术框架 ...
- docker批量操作容器
author:headsen chen date: 2019-08-07 15:26:46 列出所有的容器 ID docker ps -aq 停止所有的容器 docker stop $(docker ...
- Android开发三步骤
产品经理给需求,UI给图片 开发 *写布局文件 *写Java代码 测试
- 算法习题---5.1大理石在哪(UVa10474)
一:题目 现有N个大理石,每个大理石上写了一个非负整数.首先把各数从小到大排序,然后回答Q个问题.每个问题问是否有一个大理石写着某个整数x,如果是,还要回答哪个大理石上写着x.排序后的大理石从左到右编 ...
- Mysql关键字之Group By(二)
原文地址,优先更新https://hhe0.github.io 我们在上一节简单介绍了Mysql中group by关键字的用法,没有看过的同学点击这里了解一下; 文中提到的courses表和相关记录可 ...
- JS的正则表达式限定开始和结尾等测试
[]:匹配该区间内人任意一个字符^:匹配以某内容开头的$:匹配以模拟内容结尾的字符\w:测试是英文字母,数字,下划线.{}:设置区间,可出现几次到几次该文学习和测试几个正则的方法,测试结果如图,不加多 ...
- 关于css清除元素浮动的方法总结(overflow clear floatfix)
在前两天的一个面试中考官问我web中清除浮动的一些css常用方法,我很轻松的答出了: 1.overflow:hidden 2.clear:both 3.floatfix类 然后问题就来了,考官接着问' ...
- C#自带的Version判断版本号的大小
Version version1 = new Version("1.0.0.25"); Version version2 = new Version("1.0.0.24& ...
- 常见问题:Web/Servlet生命周期与Spring Bean生命周期
Servlet生命周期 init()初始化阶段 Servlet容器加载Servlet(web.xml中有load-on-startup=1;Servlet容器启动后用户首次向Servlet发请求;Se ...