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

论坛 期权论坛 期权     
CSDN   2019-7-14 05:08   3277   0



作者 | 漫话编程
责编 | 伍杏玲
本文经授权转载自漫话编程(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 ObjectUser1 user = new User1();user.setName("hollis");user.setAge(23);System.out.println(user);//Write Obj to FileObjectOutputStream oos = null;try {    oos = new ObjectOutputStream(new FileOutputStream("tempFile"));    oos.writeObject(user);} catch (IOException e) {    e.printStackTrace();} finally {    IOUtils.closeQuietly(oos);}//Read Obj from FileFile file = new File("tempFile");ObjectInputStream ois = null;try {    ois = new ObjectInputStream(new FileInputStream(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 ObjectUser1 user = new User1();user.setName("hollis");user.setAge(23);System.out.println(user);//Write Obj to FileObjectOutputStream oos = null;try {    oos = new ObjectOutputStream(new FileOutputStream("tempFile"));    oos.writeObject(user);} catch (IOException e) {    e.printStackTrace();} finally {    IOUtils.closeQuietly(oos);}//Read Obj from FileFile file = new File("tempFile");ObjectInputStream ois = null;try {    ois = new ObjectInputStream(new FileInputStream(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();    }}

static void readNIO() {        String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";        FileInputStream fin = null;        try {            fin = new FileInputStream(new File(pathname));            FileChannel channel = fin.getChannel();            int capacity = 100;// 字节            ByteBuffer bf = ByteBuffer.allocate(capacity);            int length = -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();                }            }        }    }    static void writeNIO() {        String filename = "out.txt";        FileOutputStream fos = null;        try {            fos = new FileOutputStream(new File(filename));            FileChannel channel = fos.getChannel();            ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");            int length = 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();                }            }        }    }

public class ReadFromFile {  public static void main(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 + "]");  }}class ProfitCalculator {  public ProfitCalculator() {  }  public static void calculateTax() {  }}public class WriteToFile {  public static void main(String[] args) throws Exception {    AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(        Paths.get("/asynchronous.txt"), StandardOpenOption.READ,        StandardOpenOption.WRITE, StandardOpenOption.CREATE);    CompletionHandler handler = new CompletionHandler() {      @Override      public void completed(Integer result, Object attachment) {        System.out.println("Attachment: " + attachment + " " + result            + " bytes written");        System.out.println("CompletionHandler Thread ID: "            + Thread.currentThread().getId());      }      @Override      public void failed(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);  }}








滴滴滴,水开了。




热 文 推 荐

[/url][url=http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650723561&idx=2&sn=4d79bb3210d794f80df6356396ecf9ac&chksm=bea6a53a89d12c2cb905bfb196ac22537601386c1c0e48a0007b7720f333c69d51dda06a08d9&scene=21#wechat_redirect]Visual Basic 终于要衰落了吗?

[/url][url=http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650723561&idx=3&sn=1a27450b8f8c4729b253c8d07ae04adb&chksm=bea6a53a89d12c2ce250a85ae4f1f63f19a3323304d0a6bd967b681e0e65db04fa76d66d2c57&scene=21#wechat_redirect]华为“舵手”任正非

[/url][url=http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650723498&idx=1&sn=6eaefcfa8c5d562e161075e11112e633&chksm=bea6a57989d12c6fe91db5b270f07e582788aaf082f839b4372c6b6d6fcce3790e32614da186&scene=21#wechat_redirect]滴滴章文嵩:不仅软件开源,还向学界开放数据

[/url][url=http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650723493&idx=1&sn=8dfd22984eba81d56eb8efeff2d1b6b8&chksm=bea6a57689d12c60fcd215aac7b37d2520ac954e241037ef045b316075a8f329bd856c973761&scene=21#wechat_redirect]小米崔宝秋:小米 AIoT 深度拥抱开源
独家 | Vitalik Buterin:以太坊2.0之跨分片交易

如何在标准的机器学习流程上玩出新花样?
面试官:你简历中写用过docker,能说说容器和镜像的区别吗?
C++、Python、Rust、Scala构建编译器的差异性究竟有多大?
马云曾经偶像,终于把阿里留下的1400亿败光了!
你点的每个“在看”,我都认真当成了喜欢
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:65
帖子:240
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP