zoukankan      html  css  js  c++  java
  • java的NIO和AIO

    1. 什么是NIO

    NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性:

    • NIO是基于块(Block)的,它以块为基本单位处理数据 (硬盘上存储的单位也是按Block来存储,这样性能上比基于流的方式要好一些)

    • 为所有的原始类型提供(Buffer)缓存支持

    • 增加通道(Channel)对象,作为新的原始 I/O 抽象

    • 支持锁(我们在平时使用时经常能看到会出现一些.lock的文件,这说明有线程正在使用这把锁,当线程释放锁时,会把这个文件删除掉,这样其他线程才能继续拿到这把锁)和内存映射文件的文件访问接口 

    • 提供了基于Selector的异步网络I/O

    所有的从通道中的读写操作,都要经过Buffer,而通道就是io的抽象,通道的另一端就是操纵的文件。

    2. Buffer

    Java中Buffer的实现。基本的数据类型都有它对应的Buffer

    Buffer的简单使用例子:

    public class Test {
        public static void main(String[] args) throws Exception {
    
            FileInputStream fin = new FileInputStream(new File("d:\buffer.tmp"));
    
            FileChannel fc = fin.getChannel();
    
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    
            fc.read(byteBuffer);
    
            fc.close();
    
            byteBuffer.flip();//读写转换
    
        }
    
    }

    总结下使用的步骤是: 

    1. 得到Channel

    2. 申请Buffer

    3. 建立Channel和Buffer的读/写关系

    4. 关闭

    下面的例子是使用NIO来复制文件:

    public static void nioCopyFile(String resource, String destination)
                throws IOException {
            FileInputStream fis = new FileInputStream(resource);
            FileOutputStream fos = new FileOutputStream(destination);
            FileChannel readChannel = fis.getChannel(); // 读文件通道
            FileChannel writeChannel = fos.getChannel(); // 写文件通道
            ByteBuffer buffer = ByteBuffer.allocate(1024); // 读入数据缓存
            while (true) {
                buffer.clear();
                int len = readChannel.read(buffer); // 读入数据
                if (len == -1) {
                    break; // 读取完毕
                }
                buffer.flip();
                writeChannel.write(buffer); // 写入文件
            }
            readChannel.close();
            writeChannel.close();
        }

    Buffer中有3个重要的参数:位置(position)、容量(capactiy)和上限(limit)

     这里要区别下容量和上限,比如一个Buffer有10KB,那么10KB就是容量,我将5KB的文件读到Buffer中,那么上限就是5KB。

    Buffer中大多数的方法都是去改变这3个参数来达到某些功能的:

    public final Buffer rewind()     将position置零,并清除标志位(mark)

    public final Buffer clear()        将position置零,同时将limit设置为capacity的大小,并清除了标志mark

    public final Buffer flip()           先将limit设置到position所在位置,然后将position置零,并清除标志位mark,通常在读写转换时使用

    文件映射到内存

    public static void main(String[] args) throws Exception {
            RandomAccessFile raf = new RandomAccessFile("C:\mapfile.txt", "rw");
            FileChannel fc = raf.getChannel();
            // 将文件映射到内存中
            MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0,
                    raf.length());
            while (mbb.hasRemaining()) {
                System.out.print((char) mbb.get());
            }
            mbb.put(0, (byte) 98); // 修改文件
            raf.close();
        }

    3. Channel 

    Channel有点类似于流,一个Channel可以和文件或者网络Socket对应。

    selector是一个选择器,它可以选择某一个Channel,然后做些事情。

    一个线程可以对应一个selector,而一个selector可以轮询多个Channel,而每个Channel对应了一个Socket。

    当selector调用select()时,会查看是否有客户端准备好了数据。当没有数据被准备好时,select()会阻塞。

    selectNow()与select()的区别在于,selectNow()是不阻塞的,当没有客户端准备好数据时,selectNow()不会阻塞,将返回0,有客户端准备好数据时,selectNow()返回准备好的客户端的个数。平时都说NIO是非阻塞的,但是如果没有数据被准备好还是会有阻塞现象。

    当有数据被准备好时,调用完select()后,会返回一个SelectionKey,SelectionKey表示在某个selector上的某个Channel的数据已经被准备好了。 

    只有在数据准备好时,这个Channel才会被选择。

    这样NIO实现了一个线程来监控多个客户端。

    NIO和AIO的区别和总结

    nio:

    1. NIO会将数据准备好后,再交由应用进行处理,数据的读取/写入过程依然在应用线程中完成,只是将等待的时间剥离到单独的线程中去。

    2. 节省数据准备时间(因为Selector可以复用)

    aio:

    1. 完了再通知我(内核内存拷贝到工作内存到过程)

    2. 不会加快IO,只是在读完后进行通知

    3. 使用回调函数,进行业务处理 

    NIO是同步非阻塞的

    AIO是异步非阻塞的

    由于NIO的读写过程依然在应用线程里完成,所以对于那些读写过程时间长的,NIO就不太适合。

    而AIO的读写过程完成后才被通知,所以AIO能够胜任那些重量级,读写过程长的任务。

  • 相关阅读:
    解决:Google代码achartengine曲线代码报错问题(转)
    操作SQLite数据库
    让服务器iis支持.apk文件下载的设置方法
    怎么在手机上查看sqlite db
    Android 3D滑动菜单完全解析,实现推拉门式的立体特效
    android自动更新程序,安装完以后就什么都没有了,没有出现安装成功的界面的问题
    那些年不错的Android开源项目
    PL/SQL Developer 连接新数据库
    Oracle 连接 Visual Studio 的工具
    利用SQLiteOpenHelper来管理SQLite数据库 (转)
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/5855362.html
Copyright © 2011-2022 走看看