java io bio nio面试题_漫画:一文学会面试中常问的 IO 问题!

原标题:漫画:一文学会面试中常问的 IO 问题!

作者 | 漫话编程

责编 | 伍杏玲

本文经授权转载自漫话编程(ID:mhcoding)

周末午后,在家里面进行电话面试,我问了面试者几个关于IO的问题,其中包括什么是BIO、NIO和AIO?三者有什么区别?具体如何使用等问题,但是面试者回答的并不是很满意。于是我在面试评价中写道:"对Java的IO提醒理解不够深入"。恰好被女朋友看到了。

faffab8bf647ec12602fde8f218d1bdd.png

1485b9547cbbb4f3fd75c05f73a8e757.png

a6952dd331a1096b7f45ec843976c479.png

970b54339608177bd9738b961fbdd276.png

Java IO

IO,常协作I/O,是Input/Output的简称,即输入/输出。通常指数据在内部存储器(内存)和外部存储器(硬盘、优盘等)或其他周边设备之间的输入和输出。

输入/输出是信息处理系统(例如计算机)与外部世界(可能是人类或另一信息处理系统)之间的通信。

在Java中,提供了一些列API,可以供开发者来读写外部数据或文件。我们称这些API为Java IO。

IO是Java中比较重要,且比较难的知识点,主要是因为随着Java的发展,目前有三种IO共存。分别是BIO、NIO和AIO。

20d227fcead8938ac82cda8429d99f91.png

1ce7df610b53fcda8ffad4793703efdd.png

29b4487138f8ca9e2f7400f42197bf16.png

Java BIO、NIO

BIO 全称Block-IO 是一种同步且阻塞的通信模式。是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。

Java NIO,全程 Non-Block IO ,是Java SE 1.4版以后,针对网络传输效能优化的新功能。是一种非阻塞同步的通信模式。

NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。

面向流的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。

面向块的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

Java AIO

Java AIO,全程 Asynchronous IO,是异步非阻塞的IO。是一种非阻塞异步的通信模式。

在NIO的基础上引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

438bfd655ca6935e9a7dde4f62fc7dd1.png

ebf64469e601e587be619f4f5161d1af.png

e2be3273bcbf38e9bd1e38294496ed8f.png

6c57e7532cee605658145d6e91dbe9ba.png

三种IO的区别

首先,我们站在宏观的角度,重新画一下重点:

BIO (Blocking I/O):同步阻塞I/O模式。

NIO (New I/O):同步非阻塞模式。

AIO (Asynchronous I/O):异步非阻塞I/O模型。

那么,同步阻塞、同步非阻塞、异步非阻塞都是怎么回事呢?关于这部分内容也可以查看《漫话:如何给女朋友解释什么是IO中的阻塞、非阻塞、同步、异步?》。

同步阻塞模式:这种模式下,我们的工作模式是先来到厨房,开始烧水,并坐在水壶面前一直等着水烧开。

异步非阻塞I/O模型:这种模式下,我们的工作模式是先来到厨房,开始烧水,我们不一一直坐在水壶前面等,也不隔一段时间去看一下,而是在客厅看电视,水壶上面有个开关,水烧开之后他会通知我。

阻塞VS非阻塞:人是否坐在水壶前面一直等。

同步VS异步:水壶是不是在水烧开之后主动通知人。

027e49f88ddb8c44c6c4ce7015cf6335.png

efbf6e91f36652d249708bb90dee2124.png

83972f0a4d26bd4b5ece5db058d9f32e.png

eaa00240e2fcfa0c39b943d254b1fc34.png

适用场景

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

67843b3860f86bd5f0af74d667b12954.png

6b0f0e4b5457fa853ba6bae0deb044d5.png

分别使用BIO、NIO、AIO 实现文件的读取和写入:

//Initializes The Object

User1 user = newUser1;

user.setName("hollis");

user.setAge(23);

System.out.println(user);

//Write Obj to File

ObjectOutputStream oos = null;

try{

oos = newObjectOutputStream(newFileOutputStream("tempFile"));

oos.writeObject(user);

} catch(IOException e) {

e.printStackTrace;

} finally{

IOUtils.closeQuietly(oos);

}

//Read Obj from File

File file = newFile("tempFile");

ObjectInputStream ois = null;

try{

ois = newObjectInputStream(newFileInputStream(file));

User1 newUser = (User1) ois.readObject;

System.out.println(newUser);

} catch(IOException e) {

e.printStackTrace;

} catch(ClassNotFoundException e) {

e.printStackTrace;

} finally{

IOUtils.closeQuietly(ois);

try{

FileUtils.forceDelete(file);

} catch(IOException e) {

e.printStackTrace;

}

}

//Initializes The Object

User1 user = newUser1;

user.setName("hollis");

user.setAge(23);

System.out.println(user);

//Write Obj to File

ObjectOutputStream oos = null;

try{

oos = newObjectOutputStream(newFileOutputStream("tempFile"));

oos.writeObject(user);

} catch(IOException e) {

e.printStackTrace;

} finally{

IOUtils.closeQuietly(oos);

}

//Read Obj from File

File file = newFile("tempFile");

ObjectInputStream ois = null;

try{

ois = newObjectInputStream(newFileInputStream(file));

User1 newUser = (User1) ois.readObject;

System.out.println(newUser);

} catch(IOException e) {

e.printStackTrace;

} catch(ClassNotFoundException e) {

e.printStackTrace;

} finally{

IOUtils.closeQuietly(ois);

try{

FileUtils.forceDelete(file);

} catch(IOException e) {

e.printStackTrace;

}

}

staticvoidreadNIO{

String pathname = "C:UsersadewDesktopjd-gui.cfg";

FileInputStream fin = null;

try{

fin = newFileInputStream(newFile(pathname));

FileChannel channel = fin.getChannel;

intcapacity = 100;// 字节

ByteBuffer bf = ByteBuffer.allocate(capacity);

intlength = -1;

while((length = channel.read(bf)) != -1) {

bf.clear;

byte[] bytes = bf.array;

System.out.write(bytes, 0, length);

System.out.println;

}

channel.close;

} catch(FileNotFoundException e) {

e.printStackTrace;

} catch(IOException e) {

e.printStackTrace;

} finally{

if(fin != null) {

try{

fin.close;

} catch(IOException e) {

e.printStackTrace;

}

}

}

}

staticvoidwriteNIO{

String filename = "out.txt";

FileOutputStream fos = null;

try{

fos = newFileOutputStream(newFile(filename));

FileChannel channel = fos.getChannel;

ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");

intlength = 0;

while((length = channel.write(src)) != 0) {

System.out.println("写入长度:"+ length);

}

} catch(FileNotFoundException e) {

e.printStackTrace;

} catch(IOException e) {

e.printStackTrace;

} finally{

if(fos != null) {

try{

fos.close;

} catch(IOException e) {

e.printStackTrace;

}

}

}

}

publicclassReadFromFile{

publicstaticvoidmain(String[] args) throws Exception{

Path file = Paths.get("/usr/a.txt");

AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);

ByteBuffer buffer = ByteBuffer.allocate(100_000);

Future result = channel.read(buffer, 0);

while(!result.isDone) {

ProfitCalculator.calculateTax;

}

Integer bytesRead = result.get;

System.out.println("Bytes read ["+ bytesRead + "]");

}

}

classProfitCalculator{

publicProfitCalculator{

}

publicstaticvoidcalculateTax{

}

}

publicclassWriteToFile{

publicstaticvoidmain(String[] args) throws Exception{

AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(

Paths.get("/asynchronous.txt"), StandardOpenOption.READ,

StandardOpenOption.WRITE, StandardOpenOption.CREATE);

CompletionHandler handler = newCompletionHandler {

@Override

publicvoidcompleted(Integer result, Object attachment) {

System.out.println("Attachment: "+ attachment + " "+ result

+ " bytes written");

System.out.println("CompletionHandler Thread ID: "

+ Thread.currentThread.getId);

}

@Override

publicvoidfailed(Throwable e, Object attachment) {

System.err.println("Attachment: "+ attachment + " failed with:");

e.printStackTrace;

}

};

System.out.println("Main Thread ID: "+ Thread.currentThread.getId);

fileChannel.write(ByteBuffer.wrap("Sample".getBytes), 0, "First Write",

handler);

fileChannel.write(ByteBuffer.wrap("Box".getBytes), 0, "Second Write",

handler);

}

}

2226ca6a59f2e1e60177a99ae627d674.png

1e64542de5d8dfc331ea8cfa000ab5f8.png

4aaf9928978a96d82129b11cbdcce9ef.png

8db16287b8e0cdba70de08a6080d870b.png

滴滴滴,水开了。

责任编辑:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值