这段时间在学些Java nio。由于平时其实比较少编写代码进行文件的读写,所以对Java的io接口,本身都比较少了解——因为平时读取文件,一般就是properties 或者 xml文件的读取,很多时候是为了实现配置的读取,而properties的读取,一般采用是Java 的 properties类,而xml的区域,则是用 Jaxb,所以对Java io了解比较少。由于最近想学习Java nio和netty,因此专门了解了下nio。
由于使用Java io的经验不足,本次对文件操作就不是很了解,所以其实刚看Java nio的时候,说实话,其实还是蛮困惑的,网上找来的例子,要么过于简单,要么不全,我一直不理解,到底Java nio哪里比Java传统的IO 快在哪里了。网上的很多例子,笼统的讲它是非阻塞的,然后读取文件的时候,立即返回,然后什么你可以去处理其它事情,直接数据返回什么的balabala什么的。说实现的,确实不太懂。例如下面这个例子:
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buf.flip();
while(buf.hasRemaining()){
System.out.print((char) buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();
这个是网上找来的例子,说实在的,后来我觉得这例子非常的不好,这个例子是可以说明Java可以这么写,但是我觉得作为NIO的范例代码的话,会使得读者非常困惑的,这到底哪里可以体现NIO比传统IO快了,我专门写了另外一个例子进行比较,用传统IO的方式编写的:
FileInputStream f = new FileInputStream(new File("argument.txt"));
byte[] bu = new byte[48];
int c;
while ((c = f.read(bu)) != -1) {
.......
}
System.out.println("2Total cost: " + (System.currentTimeMillis() - startTIme) / 1);
用上面这种方式和NIO提到的例子比较,后者还更快些。
Java NIO是非阻塞 同步IO,每次从文件或者从网络读取的返回的数据,不一定是完整的数据,这样就要求应用需要不断轮训去看是否数据读取完整了,这样岂不是更消耗CPU?
这两天渐渐学习,逐步了解接NIO的一些机制和更好采用NIO来提供系统系能的例子,记录并分享之。
说起NIO,之前讲到是异步阻塞IO,那么IO类型已同异步或者阻塞非阻塞,其实可以分几种的:
- 同步阻塞IO:Java传统的IO就是属于这种,它提供的读取数据的API,会一直阻塞到系统返回数据给调用方。同步阻塞IO应该从我们理解上和程序实现上,都是比较自然和简单的。所以早期的IO才会是这种实现方式。
- 同步非阻塞IO:Java NIO就是属于这种方式。非阻塞同步是会立即返回控制权给调用者的。调用者不需要等等,它从调用的函数获取两种结果:要么此次调用成功进行了;要么系统返回错误标识告诉调用者当前资源不可用,
- 异步非阻塞IO:异步阻塞IO是掉用获取数据的接口之后,会立即返回,而且一般框架会提供注册机制,当读取读取完毕之后,会调用注册方法或者发送消息给监听方。有兴趣的朋友可以搜索下 Proactor模式 ,了解下异步非阻塞IO。
基于同步阻塞IO的编程,编写代码简单,好维护,出了问题也好解决。应该说,在一些比较传统的简单文件读写上,使用这种方式还是比较好的:比如所,你如果只是想读取配置文件,或者想把上传的文件写到硬盘中,那么这种方式写的代码纪简单,开发也快速。
同步非阻塞IO,我们这里主要指Java NIO ,这种方式应该用服务器开发,读写Socket方式上,通过一些技巧,可以开发出性能比较好、吞吐量比较大的应用。对于文件的读取,由于它可以内存方式映射文件,可以实现比较好的随机访问,一些应用:例如IO的读写,利用NIO可以提高性能。
异步非阻塞的IO,Java中没有这种实现,等以后了解到在进行研究吧。
待续。。。