NIO Channel的学习笔记总结
摘自:http://blog.csdn.net/tsyj810883979/article/details/6876603
1.1 非阻塞模式
Java NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能瓶颈通常在I/O读写,包括对端口和文件的操作上,过去,在打开一个I/O通道后,read()将一直等待在端口一边读取字节内容,如果没有内容进来,read()也是傻傻的等,这会影响我们程序继续做其他事情,那么改进做法就是开设线程,让线程去等待,但是这样做也是相当耗费资源(传统socket通讯服务器设计模式)的。
Java NIO非堵塞技术实际是采取Reactor模式,或者说是Observer模式为我们监察I/O端口,如果有内容进来,会自动通知我们,这样,我们就不必开启多个线程死等,从外界看,实现了流畅的I/O读写,不堵塞了。
Java NIO出现不只是一个技术性能的提高,你会发现网络上到处在介绍它,因为它具有里程碑意义,从JDK1.4开始,Java开始提高性能相关的功能,从而使得Java在底层或者并行分布式计算等操作上已经可以和C或Perl等语言并驾齐驱。
如果你至今还是在怀疑Java的性能,说明你的思想和观念已经完全落伍了,Java一两年就应该用新的名词来定义。从JDK1.5开始又要提供关于线程、并发等新性能的支持,Java应用在游戏等适时领域方面的机会已经成熟,Java在稳定自己中间件地位后,开始蚕食传统C的领域。
NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有事件发生时,他会通知我们,传回一组 SelectionKey,我们读取这些Key,就会获得我们刚刚注册过的socketchannel,然后,我们从这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些数据。 Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮询(目前就这一个算法),一旦轮询到一个channel有所注册的事情发生,比如数据来了,他就会站起来报告,交出一把钥匙,让我们通过这把钥匙(SelectionKey表示SelectableChannel在Selector中的注册的标记)来读取这个channel的内容。
实现一:使用nio实现文件复制
- package study.nio;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.nio.channels.FileChannel;
- import java.nio.ByteBuffer;
- public class TestCopyFile {
- public static void main(String[] args) throws IOException {
- //调用FileManager类的copyFile静态方法
- FileManager.copyFile(new File("src.txt"), new File("dst.txt"));
- }
- }
- class FileManager {
- //把可能出现的异常抛给上层调用者处理
- public static void copyFile(File src, File dst)
- throws FileNotFoundException, IOException {
- //得到一个源文件对应的输入通道
- FileChannel fcin = new FileInputStream(src).getChannel();
- //得到一个目标文件对应的输出通道
- FileChannel fcout = new FileOutputStream(dst).getChannel();
- //生成一个1024字节的ByteBuffer实例
- ByteBuffer buf = ByteBuffer.allocate(1024);
- while(fcin.read(buf) != -1) {
- buf.flip(); //准备写
- fcout.write(buf);
- buf.clear(); //准备读
- }
- }
- }
还可以使用下面方式进行操作,在FileChannel中有两个特殊方法可以允许我们直接将两个通道相连:
long transferFrom(ReadableByteChannel src, long position, long count);
long transferTo(long position, long count, WriteableByteChannel targets);
上面while循环可以替换为:
fcin.transferTo(0, fcin.size(), fcout); 或者 fcout.transferFrom(fcin, 0, fcin.size());
实现二:向一个空文件中写入some text,再以只读方式打开该文件,在尾部追加some more,最终将该文件内容输出。
- package study.nio;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.RandomAccessFile;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- public class GetChannel {
- //为了使代码明晰,暂不处理异常
- public static void main(String[] args) throws Exception {
- FileChannel fc = null;
- //向一个文件中写入文本
- fc = new FileOutputStream(new File("data.txt")).getChannel();
- fc.write(ByteBuffer.wrap("some text".getBytes()));
- fc.close();
- //以读写方式打开文件,并在尾部追加内容
- fc = new RandomAccessFile("data.txt", "rw").getChannel();
- fc.position(fc.size());
- fc.write(ByteBuffer.wrap("some more".getBytes()));
- fc.close();
- //将文件里的内容读出来
- fc = new FileInputStream("data.txt").getChannel();
- ByteBuffer buf = ByteBuffer.allocate(1024);
- fc.read(buf);
- buf.flip();
- while(buf.hasRemaining()) {
- System.out.print((char)buf.get());
- }
- }
- }
以上均使用的是字节操作流,与nio相一致。Reader和Writer这些字符模式类不能用于产生通道,但是java.nio.channels.Channels类中提供了实用方法,可以在通道中产生Reader和Writer。 Channels.newReader(); Channels.newWriter();
实现三:将一个大文件映射到内存并查找指定的文本内容是否在该文件中(曾记得李开复与微软的故事,当然李开复是从邮件中查找信息,并且邮件被截成了图片,⊙﹏⊙b汗)
- public class LargeMappedFiles {
- public static void main(String args[]) {
- try {
- File[] files = new File[] {new File("src1.txt"), new File("src2.txt")};
- ArrayList<String> ls = search(files, "something is wrong");
- for(int i=0; i<ls.size(); i++) {
- System.out.println(ls.get(i));
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- //实现简单的内容检索
- private static ArrayList<String> search(File[] files, String text) throws Exception {
- //把检索结果放到一个list中
- ArrayList<String> result = new ArrayList<String>();
- //循环遍历文件
- for(File src : files) {
- //将整个文件映射到内存
- MappedByteBuffer dst = new RandomAccessFile(src, "rw")
- .getChannel()
- .map(FileChannel.MapMode.READ_WRITE, 0, src.length());
- //对字符进行解码
- String str = Charset.forName("UTF-8").decode(dst).toString();
- //准备进行读
- dst.flip();
- if(str.indexOf(text) != -1) {
- result.add(src.getName());
- }
- //准备写
- dst.clear();
- }
- return result;
- }
- }
实现四:在前面的学习中了解到nio为所有原始数据类型提供了Buffer支持,并且在ByteBuffer中实现了asXBuffer()方法直接将一个ByteBuffer转换成其它类型的Buffer。本例实现数据类型的转换。
- import java.nio.IntBuffer;
- import java.nio.FloatBuffer;
- import java.nio.ByteBuffer;
- import java.util.Arrays;
- public class CastBuffer {
- static byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 'a', 'b', 'c'};
- public static void main(String[] args) {
- ByteBuffer bBuf = ByteBuffer.wrap(bytes);
- System.out.println(Arrays.toString(bBuf.array()));
- //转换成IntBuffer
- IntBuffer iBuf = ((ByteBuffer)bBuf.rewind()).asIntBuffer();
- while(iBuf.hasRemaining()) {
- System.out.print(iBuf.get()+",");
- }
- //转换成FloatBuffer
- FloatBuffer fBuf = ((ByteBuffer)bBuf.rewind()).asFloatBuffer();
- while(fBuf.hasRemaining()) {
- System.out.print(fBuf.get()+",");
- }
- }
- }
其它类型转换与上面方法类似,各种方法都相似。
NIO Channel的学习笔记总结的更多相关文章
- Java NIO 学习笔记(一)----概述,Channel/Buffer
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 完全学习笔记(转)
本篇博客依照 Java NIO Tutorial翻译,算是学习 Java NIO 的一个读书笔记.建议大家可以去阅读原文,相信你肯定会受益良多. 1. Java NIO Tutorial Java N ...
- Java NIO 核心组件学习笔记
背景知识 同步.异步.阻塞.非阻塞 首先,这几个概念非常容易搞混淆,但NIO中又有涉及,所以总结一下[1]. 同步:API调用返回时调用者就知道操作的结果如何了(实际读取/写入了多少字节). 异步:相 ...
- Java NIO学习笔记
Java NIO学习笔记 一 基本概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执 ...
- Java NIO 学习笔记(七)----NIO/IO 的对比和总结
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(四)----文件通道和网络通道
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(三)----Selector
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
随机推荐
- X11/extensions/XShm.h: No such file or directory
CentOS 编译一些开源项目提示:X11/extensions/XShm.h: No such file or directory. 运行命令:yum install libXext-devel就可 ...
- java 核心技术卷一笔记 6 .2.3 接口 lambda 表达式 内部类
6.2.3 对象克隆 Cloneable 接口,这个接口指示一个类提供了一个安全的clone方法.(稍作了解) 为一个对象引用的变量建立副本时,原变量和副本都是同一个对象的引用,任何一个变量改变都 ...
- WPF中退出时显示是否保存数据提示
一.通过窗体中的按钮实现退出时数据保存提示 Xaml: <Grid> <TextBlock HorizontalAlignment="Left" Margin=& ...
- HTML之网页的基本介绍
一.web的基本介绍 web就是world wide web的缩写,称之为全球广域网,俗称WWW 可以将web理解成一种当前的互联网,对于我们来说更多的就是网站服务 网站我们可以理解成是由很多网页组合 ...
- 火狐浏览器返回不加载JS
火狐浏览器 go(-1),返回后不加载JS,谷歌会加载. 总结: Firefox和Safari在back时不会触发load, ready事件! 解决方法: $(window).unload(funct ...
- JavaScript中数据类型和typeof返回的数据类型
除了上图,要注意三点:1.symbol是ES6中新增的数据类型 2.typeof(null)结果是Object 3.typeof(Object)和typeof(Array)的结果是function,因 ...
- Vue之父子组件的通信
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ios 序列化
1到底这个序列化有啥作用? 面向对象的程序在运行的时候会创建一个复杂的对象图,经常要以二进制的方法序列化这个对象图,这个过程叫做Archiving. 二进制流可以通过网络或写入文件中(来源于某教材的一 ...
- 基于Vue+VueRouter+ModJS+Fis3快速搭建H5项目总结
技术选型 • 框架 - Vue+VueRouter • 相比较于react/angular/avalon ? • 简单轻量,社区配套完整• 模块化 - ModJS • 相比较于require/seaj ...
- 分享一个C++与Python开发的中小型通用游戏服务端框架(跨平台,开源,适合MMORPG游戏)
在开发一款游戏项目时,在立项时我们往往会考虑或者纠结很多,比如: 1,对于开发来说:服务端和客户端应该选择什么语言?用什么协议通信才更效率?协议后期如何维护?Socket是用长连接还是短连接?TCP还 ...