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

作者 | 漫话编程

责编 | 伍杏玲

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

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

Java IO

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

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

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

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

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的基础上引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

三种IO的区别

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

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

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

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

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

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

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

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

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

适用场景

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

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

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

分别使用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);

}

}

滴滴滴,水开了。

责任编辑:

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

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

    作者 | 漫话编程 责编 | 伍杏玲 本文经授权转载自漫话编程(ID:mhcoding) 周末午后,在家里面进行电话面试,我问了面试者几个关于IO的问题,其中包括什么是BIO.NIO和AIO?三者有什 ...

  2. java面试 设计模式_Java面试中常问到的设计模式

    面试中常问到的设计模式 什么是设计模式? ​设计模式是世界上各种各样程序员用来解决特定设计问题的尝试和测试的方法.设计模式是代码可用性的延伸 单例模式 ​保证被创建一次,节省系统开销 ​饿汉式:上来不 ...

  3. 去重 属性_面试中常问的List去重问题,你都答对了吗?

    面试中经常被问到的list如何去重,用来考察你对list数据结构,以及相关方法的掌握,体现你的java基础学的是否牢固. 我们大家都知道,set集合的特点就是没有重复的元素.如果集合中的数据类型是基本 ...

  4. python程序员面试题精选100题_在Python程序员面试中被问的最多的10道题

    我们在为大家整Python程序员面试试题中,发现了一些被面试官问到的最多的一些问题,以下就是本篇内容: Python是个非常受欢迎的编程语言,随着近些年机器学习.云计算等技术的发展,Python的职位 ...

  5. Java面试中常问的数据库方面问题

    MySQL 为什么用自增列作为主键 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引.如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作 ...

  6. Java面试中常问的Spring方面问题

    1.一般问题 1.1. 不同版本的 Spring Framework 有哪些主要功能? VersionFeatureSpring 2.5发布于 2007 年.这是第一个支持注解的版本.Spring 3 ...

  7. Java面试中常问的Spring方面问题(涵七大方向共55道题,含答案)

    Spring Framework 现在几乎已成为 Java Web 开发的标配框架.那么,作为 Java 程序员,你对 Spring 的主要技术点又掌握了多少呢?不妨用本文的问题来检测一下. 1.一般 ...

  8. Java面试中常问的计算机网络方面问题

    GET 和 POST 区别 (GET)请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:/test/demo_form.asp?name1=value1&name2=va ...

  9. post大小限制_作为一个程序员,面试中常问的get和post的区别,你真的知道吗

    作为一个程序员无论是搞前端的还是搞后端的,只要问起来GET和POST的区别,都能说出来个一二三四来. 你可能自己写过无数个GET和POST请求,或者也看过很多权威网站总结出来的区别,你非常清楚的知道什 ...

最新文章

  1. 《Java工程师成神之路》终于免费开放下载了!
  2. 【005】◀▶ C#学习笔记(四)(集合)
  3. centos7安装docker并配置阿里云镜像
  4. Arrays.asList(arr)使用注意事项
  5. 【计算机组成原理】双端口RAM和多模块存储器
  6. php aes加密解密_JAVA实现PHP的openssl_encrypt方法
  7. @PreDestroy 为什么不执行
  8. 无线网络安全技术基础
  9. 如何画一个算法流图?
  10. Java聊天室——一对一模式
  11. idea发现git出现cannot run git:cannot identify version of git executable :no response
  12. 上手 WebRTC DTLS 遇到很多 BUG,怎么解?
  13. Linux系统rar格式怎么解压,如何在linux下解压缩rar格式的文件压缩包
  14. 路由器工作原理及其主要部件详解
  15. HDU-1425 排序
  16. Go 使用 buger/jsonparser 优化反序列化性能
  17. 如何在服务器上部署静态网页,让所有人都能访看到?
  18. 图像预处理: 规范化
  19. JavaWeb学习笔记——JSP
  20. Mysql添加用户,访问指定数据库

热门文章

  1. 如何使用Disk Drill清理Mac Disk Drill for Mac的使用方法
  2. drill支持的数据类型
  3. 全国职称计算机考试攻略,全国职称计算机考试轻松通关的技巧
  4. 5款民间丰胸食谱帮你变丰满
  5. 笔记本发烫、风扇太响的一个原因
  6. 【聊天机器人测评】独立站插件用Tidio还是Zendesk?
  7. 我的微信又被限制了!
  8. 如何合规申请商家码?
  9. OC中JSON解析与XML解析
  10. 从零开发一款相机 第五篇:Camera api1实现预览、拍照、录像功能