BIO和NIO

BIO在之前的服务器处理模型中,在调用ServerSocket.accept()方法时,会一直阻塞到有客户端连接才会返回,每个客户端连接过来后,服务端都会accept一个新连接,接着启动一个线程去处理该客户端的请求。在这个新的线程中,也会在read()方法中阻塞,直到读取完数据,处理完成后销毁该处理线程。

这样会有什么问题呢?

当客户端并发访问增加后,服务端线程个数膨胀,频繁出现由于IO阻塞导致挂起的线程,系统性能将急剧下降,容易发生线程堆栈溢出、创建新线程失败等问题。

阻塞导致大量线程资源被浪费;阻塞可导致大量的上下文切换,很多切换其实是无意义的

Java自1.4以后,加入了新IO特性NIO,NIO带来了non-blocking特性。

那么NIO是如何帮助我们解决这种问题的呢(反应器设计模式)?

1). 由一个专门的线程来处理所有的 IO 事件,并负责分发。 
2). 事件驱动机制:事件到的时候触发,而不是同步的去监视事件。 
3). 线程通讯:线程之间通过 wait,notify 等方式通讯。保证每次上下文切换都是有意义的。减少无谓的线程切换。

服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件。我们以服务端为例,如果服务端的selector上注册了读事件,某时刻客户端给服务端发送了一些数据,NIO的服务端会在selector中添加一个读事件。服务端的处理线程会轮询地访问selector,如果访问selector时发现有感兴趣的事件到达,则处理这些事件,如果没有感兴趣的事件到达,则处理线程会一直阻塞直到感兴趣的事件到达为止。

1、IO的例子

/* 字节IO */
public void byteIO() throws FileNotFoundException, IOException {
FileInputStream fin = new FileInputStream(new File(
"D:\\test\\byteio_in.txt"));
FileOutputStream fout = new FileOutputStream(new File(
"D:\\test\\byteio_out.txt"));
int c = -1;
while ((c = fin.read()) != -1) {
fout.write(c);
}
fin.close();
fout.close();
} /* 字符IO */
public void charIO() throws FileNotFoundException, IOException {
FileReader reader = new FileReader(new File("D:\\test\\chario_in.txt",
""));
FileWriter writer = new FileWriter(new File("D:\\test\\chario_out.txt"));
char[] charArr = new char[512];
while (reader.read(charArr) != -1) {
writer.write(charArr);
}
reader.close();
writer.close();
} /* bufferIO */
public void bufferIO() throws FileNotFoundException, IOException {
BufferedInputStream bufferReader = new BufferedInputStream(
new FileInputStream("D:\\test\\bufferio_in.txt"));
BufferedOutputStream bufferWriter = new BufferedOutputStream(
new FileOutputStream("D:\\test\\bufferio_out.txt"));
int c = -1;
while ((c = bufferReader.read()) != -1) {
bufferWriter.write(c);
}
bufferReader.close();
bufferWriter.close();
}

2、NIO的例子

/* NIO */
public void NIO() throws FileNotFoundException, IOException {
FileInputStream fin = new FileInputStream("D:\\test\\nio_in.txt");
FileOutputStream fout = new FileOutputStream("D:\\test\\nio_out.txt");
FileChannel finChannel = fin.getChannel();
FileChannel foutChannel = fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(512);
while (finChannel.read(buffer) != 1)//读到缓存
{
buffer.flip();//指针跳到缓存头
foutChannel.write(buffer);
buffer.clear();//重置缓冲区
}
fin.close();
fout.close();
}

3、NIO实现非阻塞Server服务

下面是一个NIO实现Server的例子

public class MultiPortEcho {
private int ports[];
private ByteBuffer echoBuffer = ByteBuffer.allocate(1024); public MultiPortEcho(int ports[]) throws IOException {
this.ports = ports;
go();
} private void go() throws IOException {
// Create a new selector
Selector selector = Selector.open(); // Open a listener on each port, and register each one with the selector
for (int i = 0; i < ports.length; ++i) {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ServerSocket ss = ssc.socket();
InetSocketAddress address = new InetSocketAddress(ports[i]);
ss.bind(address);
SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Going to listen on " + ports[i]);
} while (true) {
int num = selector.select();
Set selectedKeys = selector.selectedKeys();
Iterator it = selectedKeys.iterator(); while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next(); if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
// Accept the new connection
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false); // Add the new connection to the selector
SelectionKey newKey = sc.register(selector,SelectionKey.OP_READ);
it.remove(); System.out.println("Got connection from " + sc);
} else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
// Read the data
SocketChannel sc = (SocketChannel) key.channel(); // Echo data
int bytesEchoed = 0;
while (true) {
echoBuffer.clear();
int r = sc.read(echoBuffer);
if (r <= 0) {
break;
}
echoBuffer.flip();
sc.write(echoBuffer);
bytesEchoed += r;
} System.out.println("Echoed " + bytesEchoed + " from " + sc);
it.remove();
} }
}
} static public void main(String args[]) throws Exception { int ports[] = {1234,6765,7987}; for (int i = 0; i < args.length; ++i) {
ports[i] = Integer.parseInt(args[i]);
} new MultiPortEcho(ports);
}
}

参考资料:

http://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html#ibm-pcon

http://weixiaolu.iteye.com/blog/1479656

JavaIO和JavaNIO的更多相关文章

  1. Linux IO 概念(2)【转】

    转自:https://www.cnblogs.com/qq289736032/p/9188455.html 在上一篇IO底层的概念中杂合了很多模糊的概念,受知识水平的限制,只是从网上抄了很多过来.从l ...

  2. Linux IO 概念(2)

    在上一篇IO底层的概念中杂合了很多模糊的概念,受知识水平的限制,只是从网上抄了很多过来.从linux一切皆文件的设计哲学,介绍了文件描述符,从进程的运行内存分配,进程的切换,介绍了进程的阻塞,以及引出 ...

  3. JavaIO学习笔记(五)

    JavaIO前期准备 什么是同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 什么是异步 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO ...

  4. javaIO系统----再看装饰者模式

    javaIO系统拥有各种各样的类,尤其是每次要进行读写操作时,总会一层套一层的new,以前不明白为什么要这样做,不过学习了适配器模式后,对于这种做法立刻了解了:动态扩展IO的功能,使之符合使用者的习惯 ...

  5. Java学习日记之 Java-IO流

    Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节:  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...

  6. javaIO框架小析

    IO即数据读写.数据是应用的中心要素,而数据读写的能力和可扩展性是编程平台的基础支撑. 概念框架 方式: 字节流 Byte 和 字符流 Char 方向: 输入 Input 和 输出 Output : ...

  7. javaNIO(转载)

    (一) Java NIO 概述 Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Chan ...

  8. javaIO流实现读写txt文件

    javaIO流实现文件读写 文件写入: InputStreamReader BufferedReader 文件读取: FileOutputStream package javatest.basic22 ...

  9. JAVANIO通道

    package com.nio.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import j ...

随机推荐

  1. java 考试试题

    Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他.有些题来自网上搜集整理,有些题来自学员 ...

  2. flume1.5.2安装与简介

    关于flume的简介看参考:http://www.aboutyun.com/thread-7415-1-1.html 其实一张图就简单明了了 简单安装: 1.下载解压 ... 2.配置JDK,flum ...

  3. 如果是除去末尾特定字符或字符串:TrimEnd方法性能优于Remove方法

    测试用例--除去末尾特定字符或字符串,Remove方法和TrimEnd方法的比较 结论: 如果是除去末尾特定字符或字符串:TrimEnd方法性能优于Remove方法 具体测试用例如下: Stopwat ...

  4. Burn the Linked Camp(bellman 差分约束系统)

    Burn the Linked Camp Time Limit: 2 Seconds      Memory Limit: 65536 KB It is well known that, in the ...

  5. Nodejs新建博客练习(二)添加flash支持

    安装必须模块 npm install connect-flash npm install express-session 然后在app.js里面添加一些代码 var flash = require(' ...

  6. IOS开发UI篇之tableView 的用法详解

    1.我们知道tableView是IOS中的高级视图,其继承与ScrollView,故我们知道他有具有ScrollView的所有功能.而且还扩展了许多.当然在这里就不一一介绍了. 2.tableView ...

  7. CSS属性(常用的属性)

    CSS属性(常用的属性)http://www.w3school.com.cn/cssref/index.asp 一:文本与字体属性 1.字体属性 (1):font-size:字体的大小(例如:font ...

  8. Oracle数据库SQL优化

    SQL优化的最终目的是用户体验-在最短时间内让用户在页面数据.因此,执行时间是SQL优化的重要指标.在SQL查询中,I/O操作最占系统性能的.I/O操作量越大,时间越久.减少I/O操作量是优化SQL的 ...

  9. Netty4 自定义Decoder,Encoder进行对象传递

    首先我们必须知道Tcp粘包和拆包的,TCP是个“流”协议,所谓流,就是没有界限的一串数据,TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际数据进行包的划分,一个完整的包可能会被拆分 ...

  10. POJ 3164 Command Network 最小树形图模板

    最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...