Java之IO NIO AIO 的区别

Java之IO NIO AIO 的区别

IO

同步阻塞

每个请求开启一个线程
线程开启,如果当前线程没有数据可读,线程阻塞在read

IO流简单来说就是input和output流,IO流主要是用来处理设备之间的数据传输,Java IO对于数据的操作都是通过流实现的,而java用于操作流的对象都在IO包中。

按操作数据分为:字节流(InputStream、OutputStream)和字符流(Reader、Writer)
按流向分:输入流(Reader、InputStream)和输出流(Writer、OutputStream)

IO线程执行图
在这里插入图片描述

NIO

同步阻塞

一个线程并发处理多个写读
空闲线程处理其他通道IO操作

NIO的三个主要组成部分:Channel(通道)、Buffer(缓冲区)、Selector(选择器)

Channel对象,可以通过它读取和写入数据。可以把它看做是IO中的流。不同的是,Channel是双向的,既可以读又可以写,而流是单向的 ,Channel可以进行异步的读写。

Buffer对象 , 对Channel的读写必须通过Buffer对象。所有数据都通过Buffer对象处理,所以,您永远不会将字节直接写入到Channel中,相反,您是将数据写入到Buffer中;同样,您也不会从Channel中读取字节,而是将数据从Channel读入Buffer,再从Buffer获取这个字节。当向 Buffer 写入数据时,Buffer 会记录下写了多少数据。一旦要读取数据,需要通过 flip() 方法将 Buffer 从写模式切换到读模式。在读模式下,可以读取之前写入到 Buffer 的所有数据。

Selector 对象 ,多路复用器 。用于检查一个或多个Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。(Socket 通信就是NIO应用)
在这里插入图片描述

NIO线程执行图
在这里插入图片描述

AIO

NIO2,异步阻塞IO。

应用操作之后直接返回,不阻塞,后台处理完,操作系统通知相应线程进行后续操作。AIO应用不广泛。

AIO是异步IO的缩写,虽然NIO在网络操作中,提供了非阻塞的方法,但是NIO的IO行为还是同步的。对于NIO来说,我们的业务线程是在IO操作准备好时,得到通知,接着就由这个线程自行进行IO操作,IO操作本身是同步的。

但是对AIO来说,则更加进了一步,它不是在IO准备好时再通知线程,而是在IO操作已经完成后,再给线程发出通知。因此AIO是不会阻塞的,此时我们的业务逻辑将变成一个回调函数,等待IO操作完成后,由系统自动触发。

与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。 即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。 在JDK1.7中,这部分内容被称作NIO.2,主要在Java.nio.channels包下增加了下面四个异步通道:

AsynchronousSocketChannel
AsynchronousServerSocketChannel
AsynchronousFileChannel
AsynchronousDatagramChanne

在AIO编程中,发出一个事件(accept read write等)之后要指定事件处理类(回调函数),AIO中的事件处理类是CompletionHandler<V,A>,这个接口定义了如下两个方法,分别在异步操作成功和失败时被回调。

void completed(V result, A attachment);
void failed(Throwable exc, A attachment);

AIO 实例


import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class Test {

    public static void aio() throws IOException {
        String filePath = "C:/Users/clczp/Desktop/text1.txt";
        System.out.println("1.开始写入文件");
        Path path = Paths.get(filePath);
        AsynchronousFileChannel writeC = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
        ByteBuffer byteBuf = ByteBuffer.wrap("\r\nJava AIO 测试!".getBytes("utf-8"));
        writeC.write(byteBuf, writeC.size());
        writeC.close();

        System.out.println("2.读文件内容");
        AsynchronousFileChannel readC = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
        ByteBuffer bbf = ByteBuffer.allocate(1024);
        readC.read(bbf, 0, bbf, new CompletionHandler() {
            @Override
            public void completed(Integer result, ByteBuffer buffer) {
                buffer.flip();
                byte[] data = new byte[buffer.limit()];
                buffer.get(data);
                System.out.println("\t>"+new String(data)+"<");
                buffer.clear();
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("\t:>读失败了");
            }
        });
        readC.close();
        System.out.println("3.完成");
    }

    public static void main(String[] args) throws IOException {
        Test.aio();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值