• 《Java程序性能优化》3.3 使用NIO提升性能(未完)


    p:102-118

    流与NIO的不同

    流以字节为单位,NIO基于块(block)为单位。
    channel是双向的通道。stream是单向的。

    NIO组件

    NIO两个重要组件:通道channel和缓冲buffer

    通道表示缓冲数据的源头或者目的地。
    缓冲是一块连续的内存, 是NIO读写数据的中转地。

    通道(Channel)

    不能直接对channel进行读写操作,必须通过Buffer来进行。
    如: 在读一个Channel的时候,需要先将数据读入到相对应的Buffer,然后在Buffer中进行读取。
    fc=fileInputStream.getChannel()

    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);//buffer初始化的时候,pos=0,limit=capacity
    fc.read(byteBuffer)
    fc.close();
    byeBuffer.flip();//limit=pos;pos=0; 表示只能读pos--limit的内容
    

    特别注意:
    FileChannel outChannel = fileOutputStream.getChannel();
    FileChannel inChannel = fileinputStream.getChannel();
    inChannel.read(buff) 是 读取通道的内容buffer
    outChannel.write(b)是将buffer中的内容(limit到pos位置)写到通道对应的位置

    缓冲(Buffer)

    Buffer基本参数

    参数 说明
    位置(position) 当前操作的位置,0<=position<=limit<=capacity
    容量(capacity) 操作位置的最大值
    上限(limit) 读/写操作的范围 ,0<=limit<=capacity

    对Buffer的操作:clear、flip、rewind

    注意:实际没操作数据,只是操作了limit,pos。三者都会清除mark。

    **clear:**清除此缓冲区。将位置设置为 0,将限制设置为容量(limit=capacity),并丢弃标记(mark)。 :它将限制设置为容量大小,将位置设置为 0。 ps:变成初始状态,pos=0,limit=capcity=max

    **flip:**使缓冲区为一系列新的通道写入或相对获取 操作做好准备。:反转此缓冲区。首先将限制设置为当前位置,然后将位置设置为 0。如果已定义了标记,则丢弃该标记。 。 ps:规定写入读取的最大limit,limit=position,position=0;

    rewind: 使缓冲区为重新读取已包含的数据做好准备:它使限制保持不变,将位置设置为 0,并丢弃标记。 ps:position=0;丢弃掉上次pos修改。 所以可以重复读取

    mark与reset

    像书签一样, 方便快速恢复到标记的位置(position)。
    mark:在此缓冲区的位置设置标记。
    reset:改变position为之前标记的值

    public final Buffer reset()将此缓冲区的位置重置为以前标记的位置。
    调用此方法不更改也不丢弃标记的值。
    返回:
    此缓冲区
    抛出:
    InvalidMarkException - 如果尚未设置标记

    待续。。

    测试用例

    package com.gkwind.nio;
    
    import org.apache.commons.io.FileUtils;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    /**
     * @Author thewindkee
     * @Date 2019/4/18 0018 下午 12:19
     */
    public class NIOTest {
        public static void main(String[] args) throws IOException {
            testFlipAndRewind();
            testChannel();
            testMarkAndReset();
    
        }
    
    
        private static ByteBuffer prepareBuffer() {
            System.out.println("prepareBuffer");
            ByteBuffer b = ByteBuffer.allocate(15);//初始化,pos=0,limit=capacity
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=0
            for (int i = (int)'a'; i <(int)'a'+ 10; i++) {
                b.put((byte) i);
            }
            return b;
        }
        private static void testChannel() throws IOException {
            ByteBuffer b = prepareBuffer();
            b.get();
            // channel
            //limit=1
            File file = new File("a.txt");
            System.out.println(file.getAbsolutePath());
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            FileChannel outChannel = fileOutputStream.getChannel();
            outChannel.write(b);
    //        fileOutputStream.flush();
            outChannel.close();
            //文件中 包含 bcdefghij
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=10 capacity=15 position=10
    
            File bfile = new File("b.txt");
            FileUtils.write(bfile, "中国", "UTF-8");//准备数据
            FileInputStream fileInputStream = new FileInputStream(bfile);
            FileChannel inChannel = fileInputStream.getChannel();
            //清空buffer
            b.clear();//pos=0,limit=capacity
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=0
            inChannel.read(b);
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=6
            b.flip();//确定limit位置,准备读
            System.out.println(new String(b.array(),b.position(),b.limit()));//中国
        }
    
        private static void testFlipAndRewind() {
            System.out.println("testFlipAndRewind");
            //rewind and flip
            ByteBuffer b = prepareBuffer();
    //        b.put("中国".getBytes("GBK"));
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=10
            b.flip();//limit=pos,pos=0;定义能get/put的最大位置
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=10 capacity=15 position=0
            System.out.println("get...");
    //        byte[] dst = new byte[1024];
    //        b.get(dst,b.position(),b.limit());//会引起变化
    //        System.out.println(dst.length+" "+new String(dst));//abcdefghij        注意包含了空格(1024-10个)
            byte [] des2 = new byte[b.limit()];
            b.get(des2);//会引起变化
            System.out.println(new String(des2));//abcdefghij
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=10 capacity=15 position=10
            System.out.println("rewind..");
            b.rewind();//丢弃掉pos变化,pos=0; limit不变;方便重新读取
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=10 capacity=15 position=0
            System.out.println(new String(b.array(), b.position(), b.limit()));//不会改变limit
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=10 capacity=15 position=0
            System.out.println(b.get());//limit++
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=10 capacity=15 position=1
        }
     
    
    
        private static void testMarkAndReset() {
            System.out.println("testMarkAndReset");
            //mark and reset
            ByteBuffer b = prepareBuffer();
            b.clear();
            for (int i = (int)'a'; i <(int)'a'+ 10; i++) {
                b.put((byte) i);
            }
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=6
            b.flip();
            System.out.println("flip... 准备读...");
            b.get();
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=6
            b.mark();
            System.out.println("mark...");
            b.get();
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=6
    //        b.clear();//clear会清除mark的位置
            b.reset();
            System.out.println("reset...");
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=6
            b.limit(3);//会清除mark的位置
            System.out.println("limit(3)...");
            System.out.println("limit=" + b.limit() + " capacity=" + b.capacity() + " position=" + b.position());//limit=15 capacity=15 position=6
        }
    
    }
    
  • 相关阅读:
    magento设置快捷支付后,付款出现Unable to communicate with the PayPal gateway
    Magento安装插件失败出现503错误的解决方法
    magento安装插件后显示404error
    magento安装插件报connection string is empty
    mysql修改root密码
    thinkphp 3.2.3版本学习笔记
    那些年,被我蠢哭了的php代码小错误~~~
    PHP实现文件上传和下载(单文件上传、多文件上传、多个单文件上传)(面向对象、面向过程)
    php生成纯数字、字母数字、图片、纯汉字的随机数验证码
    php使用GD库实现图片水印和缩略图——封装成类
  • 原文地址:https://www.cnblogs.com/thewindkee/p/12873139.html
Copyright © 2020-2023  润新知