JavaIO和JavaNIO
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的更多相关文章
- Linux IO 概念(2)【转】
转自:https://www.cnblogs.com/qq289736032/p/9188455.html 在上一篇IO底层的概念中杂合了很多模糊的概念,受知识水平的限制,只是从网上抄了很多过来.从l ...
- Linux IO 概念(2)
在上一篇IO底层的概念中杂合了很多模糊的概念,受知识水平的限制,只是从网上抄了很多过来.从linux一切皆文件的设计哲学,介绍了文件描述符,从进程的运行内存分配,进程的切换,介绍了进程的阻塞,以及引出 ...
- JavaIO学习笔记(五)
JavaIO前期准备 什么是同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 什么是异步 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO ...
- javaIO系统----再看装饰者模式
javaIO系统拥有各种各样的类,尤其是每次要进行读写操作时,总会一层套一层的new,以前不明白为什么要这样做,不过学习了适配器模式后,对于这种做法立刻了解了:动态扩展IO的功能,使之符合使用者的习惯 ...
- Java学习日记之 Java-IO流
Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节: 字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...
- javaIO框架小析
IO即数据读写.数据是应用的中心要素,而数据读写的能力和可扩展性是编程平台的基础支撑. 概念框架 方式: 字节流 Byte 和 字符流 Char 方向: 输入 Input 和 输出 Output : ...
- javaNIO(转载)
(一) Java NIO 概述 Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Chan ...
- javaIO流实现读写txt文件
javaIO流实现文件读写 文件写入: InputStreamReader BufferedReader 文件读取: FileOutputStream package javatest.basic22 ...
- JAVANIO通道
package com.nio.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import j ...
随机推荐
- AJAX全套
AJAX概述 AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异步 Java ...
- js技巧总结
很早以前看到的代码,同时加上一些我在项目中用到的代码,感觉很实用,在这里记录下来,怕忘记了,有些代码忘记在哪看到的了,所以就不贴网址了,感谢各位大神的分享!如果有其他的好的方法,欢迎留言~ 1.取整的 ...
- Debian 8 安装 Nvidia 显卡驱动
sudo apt-get install linux-headers-$(uname -r|sed 's,[^-]*-[^-]*-,,') nvidia-kernel-dkms 正在读取软件包列表.. ...
- javaScript入门2--变量,作用域,内存
变量类型:基本类型和引用类型 基本类型上节已经提到.基本类型的值是按值传递的,既改变形参的值不会影响实参 <html> <head> <meta charset=&quo ...
- LRU在MySQL缓存池的实现
MySQL的InnoDB引擎设置有索引及数据缓存池,其中用到的LRU算法来维持缓存的命中率 这里用到了顺序表list来作为缓冲池,每个数据节点称为block 该算法采用“中点插入法”:当插入一个新bl ...
- JQuery总结:选择器归纳、DOM遍历和事件处理、DOM完全操作和动画 (转)
JQuery总结:选择器归纳.DOM遍历和事件处理.DOM完全操作和动画 转至元数据结尾 我们后台可能用到的页面一般都是用jquery取值赋值的,发现一片不错的文章 目录 JQuery总结一:选择器归 ...
- spring--mybatis事务总结
spring--事务原理.mybatis--MapperScannerConfigurer 和 mybatis--MapperProxy事务,最近想把spring mybatis中的事务和mapper ...
- Gulp 自动化的项目构建工具
在很多场合都会听到前端工和 node 程师推荐 Grunt 来实现项目的自动化,自动化可以自动完成 javascript/coffee/sass/less 等文件的的测试.检查.合并.压缩.格式化.部 ...
- 转:Android官方MVP架构示例项目解析
转自: http://www.infoq.com/cn/articles/android-official-mvp-architecture-sample-project-analysis 作者 吕英 ...
- Sharepoint 2013 系列篇(安装部署)--上篇
前言 sharepoint的部署是按照物理拓扑图的架构来部署,按照物理拓扑图架构分为一层拓扑图架构,二层拓扑图架构,三层拓扑图架构,多层拓扑图架构. 按照分层的拓扑图部署是按照需求来划分的,一层拓扑图 ...