探索Java NIO的历程
前段时间有些时间,打算看看NIO的东西,本来以为很快可以了解的东西,却用了很多时间。
首先Goole NIO可以看到很多的教程,非阻塞,Buffer,内存映射,块读取前三个很快就有所了解
尝试着写了些小程序,学习东西的时候总喜欢写点小例子。
唯独块读取没有找到对应的东西。(在过程中,主要看了IBM 的NIO入门)
首先,IBM NIO入门中的语句
--------------------------------------------------------------------------------
原来的 I/O 库(在 java.io.*中) 与 NIO 最重要的区别是数据打包和传输的方式。正如前面提到的,
原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。 面向流 的 I/O 系统一次一个字节地处
理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的 I/O 通常相当慢。 一个 面向块 的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的I/O 所具有的优雅性和简单性。
--------------------------------------------------------------------------------
首先简单的印象是NIO快,所以想写个程序验证一下.如下复制:

public
static
void
test2(String name1, String name2)
{2
long
start
=
System.currentTimeMillis();3

try
{4
FileInputStream fis
=
new
FileInputStream(name1);5
FileOutputStream fos
=
new
FileOutputStream(name2);6
byte
[] buf
=
new
byte
[
8129
];7

while
(
true
)
{ 8
int
n
=
fis.read(buf);9

if
(n
==
-
1
)
{10
break
;11
}
12
fos.write(buf,
0
,n);13
}
14
fis.close();15
fos.close();16

}
catch
(Exception e)
{17
e.printStackTrace();18
}
19
long
end
=
System.currentTimeMillis();20
long
time
=
end
-
start;21
System.out.println(time);22
}
23
24

public
static
void
test3(String name1, String name2)
{25
long
start
=
System.currentTimeMillis();26

try
{27
FileInputStream in
=
new
FileInputStream(name1);28
FileOutputStream out
=
new
FileOutputStream(name2);29
FileChannel fc1
=
in.getChannel();30
FileChannel fc2
=
out.getChannel();31
ByteBuffer bb
=
ByteBuffer.allocate(
8129
);32

while
(
true
)
{33
bb.clear();34
int
n
=
fc1.read(bb);35

if
(n
==
-
1
)
{36
break
;37
}
38
bb.flip();39
fc2.write(bb);40
}
41
fc1.close();42
fc2.close();43

}
catch
(IOException e)
{44

45
}
46
long
end
=
System.currentTimeMillis();47
long
time
=
end
-
start;48
System.out.println(time);49
}
本以为可以结束,结果测试结果出乎意料,函数一比函数二要快,就是说Old IO快于NIO ,从此
也就开始了整个过程:
为了了解这个问题,仔细搜索并仔细再看IBM 的NIO教程,看到如下这段话
---------------------------------------------
在 JDK 1.4 中原来的 I/O 包和 NIO 已经很好地集成了。 java.io.* 已经以 NIO 为基础重新实现了,
所以现在它可以利用 NIO 的一些特性。例如, java.io.* 包中的一些类包含以块的形式读写数据的方法,
这使得即使在更面向流的系统中,处理速度也会更快。 也可以用 NIO 库实现标准 I/O 功能。例如,
可以容易地使用块 I/O 一次一个字节地移动数据。但是正如您会看到的,NIO 还提供了原 I/O 包中所没有的许多好处。
---------------------------------------------
所以我想,是否因为InputStream中使用了块读取实现了呢,所以进入JDK1.4中的InputStream中
看看source,首先引起我注意的是read函数,当参数是一个byte数组的时候,直接调用的native实现
难道是这个,为了验证,下载了一个JDK1.3下来,发现JDK1.3是一样的。
继续,我想是否是JVM底层实现了块读取呢,为了证明这个我用JDK1.3和JDK1.4同时实现了类似的函数, 测试的结果再次出乎意料,性能相差不大.那就不是这个了。
为此多方查找资料,未果,为此多写几个函数,好好测试一下IO的不同。于是有了如下的一些函数
//
exec
2

public
static
void
test1(String name1, String name2)
{3
long
start
=
System.currentTimeMillis();4

try
{5
String cmd
=
"
cmd /c copy d:\\out1.txt d:\\out2.txt
"
;6
System.out.println(cmd);7
Process p
=
Runtime.getRuntime().exec(cmd);÷8
p.waitFor();9

}
catch
(Exception e)
{10
e.printStackTrace();11
}
12
long
end
=
System.currentTimeMillis();13
long
time
=
end
-
start;14
System.out.println(time);15
}
16

17
//
old io
18

public
static
void
test2(String name1, String name2)
{19
long
start
=
System.currentTimeMillis();20

try
{21
FileInputStream fis
=
new
FileInputStream(name1);22
FileOutputStream fos
=
new
FileOutputStream(name2);23

while
(
true
)
{24
byte
[] buf
=
new
byte
[
8129
];25
int
n
=
fis.read(buf);26

if
(n
==
-
1
)
{27
break
;28
}
29
fos.write(buf);30
}
31
fis.close();32
fos.close();33

}
catch
(Exception e)
{34
e.printStackTrace();35
}
36
long
end
=
System.currentTimeMillis();37
long
time
=
end
-
start;38
System.out.println(time);39
}
40

41
//
new io
42

public
static
void
test3(String name1, String name2)
{43
long
start
=
System.currentTimeMillis();44

try
{45
FileInputStream in
=
new
FileInputStream(name1);46
FileOutputStream out
=
new
FileOutputStream(name2);47
FileChannel fc1
=
in.getChannel();48
FileChannel fc2
=
out.getChannel();49
ByteBuffer bb
=
ByteBuffer.allocate(
8129
);50

while
(
true
)
{51
bb.clear();52
int
n
=
fc1.read(bb);53

if
(n
==
-
1
)
{54
break
;55
}
56
bb.flip();57
fc2.write(bb);58
}
59
fc1.close();60
fc2.close();61

}
catch
(IOException e)
{62
本文探讨了Java NIO的特点及其实现方式,并通过对比传统IO与NIO的文件复制性能,深入分析了NIO块读取的优势。通过具体代码示例展示了不同IO操作的执行效率。
1028

被折叠的 条评论
为什么被折叠?



