传统IO采用阻塞式模型,对于每个连接,都需要创建一个独立的线程来处理读写操作,而在读写的这个过程中是无法执行其他任务。这会导致大量县城的创建和销毁,以及上下文切换,降低了系统性能。
NIO使用非阻塞模型,允许线程在IO执行时执行其他任务。这种模式通过使用选择器(Selector)来监控多个通道(Channel)上的IO事件,实现了更高的性能和可伸缩性。
// 使用传统的 I/O 方法传输文件
private long transferFile(File source, File des) throws IOException {
long startTime = System.currentTimeMillis();
if (!des.exists())
des.createNewFile();
// 创建输入输出流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des));
// 使用数组传输数据
byte[] bytes = new byte[1024 * 1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
// 使用 NIO 方法传输文件
private long transferFileWithNIO(File source, File des) throws IOException {
long startTime = System.currentTimeMillis();
if (!des.exists())
des.createNewFile();
// 创建随机存取文件对象
RandomAccessFile read = new RandomAccessFile(source, "rw");
RandomAccessFile write = new RandomAccessFile(des, "rw");
// 获取文件通道
FileChannel readChannel = read.getChannel();
FileChannel writeChannel = write.getChannel();
// 创建并使用 ByteBuffer 传输数据
ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
while (readChannel.read(byteBuffer) > 0) {
byteBuffer.flip();
writeChannel.write(byteBuffer);
byteBuffer.clear();
}
// 关闭文件通道
writeChannel.close();
readChannel.close();
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static void main(String[] args) throws IOException {
SimpleFileTransferTest simpleFileTransferTest = new SimpleFileTransferTest();
File sourse = new File("[电影天堂www.dygod.cn]猜火车-cd1.rmvb");
File des = new File("io.avi");
File nio = new File("nio.avi");
// 比较传统的 I/O 和 NIO 传输文件的时间
long time = simpleFileTransferTest.transferFile(sourse, des);
System.out.println(time + ":普通字节流时间");
long timeNio = simpleFileTransferTest.transferFileWithNIO(sourse, nio);
System.out.println(timeNio + ":NIO时间");
}