Une brève introduction à JavaINO (1)

Javaino

  • Cela est Java New IOaussi appelé non-blocage IONone Blocking IO
  • Est-ce un tout nouveau et JDK 1.4plus tard fourniIO API

2. Fonction

  • Fournit une méthode de travail IOdifférente de la normeIO
  • Alternative à la norme Java IOdeIO API

3. Nouvelles fonctionnalités

En revanche Java IO, NIOles nouvelles fonctionnalités sont les suivantes

Insérez la description de l'image ici

La principale différence entre Java NIO et IO

Style IO Style NIO
Orienté octets Orienté cache
Blocage des E / S Non bloquant (IO non bloquant)
(Aucun) Sélecteurs

4. Composants principaux

Java NIOLes principaux composants comprennent:

  • Canal ( Channel)
  • Tampon ( Buffer)
  • Sélecteur ( Selectors)

5. Allocation et accès à NIO_Buffer_

  • Trois paramètres importants dans le cache
/**
    * 测试缓存分配
    */
   @Test

   public void test1(){
       // capacity 分配缓存大小
       int capacity = 1024;
       ByteBuffer buffer = ByteBuffer.allocate(capacity);

       System.out.println("capacity(缓存大小):" + buffer.capacity());
       System.out.println("limit(限制):" + buffer.limit());
       System.out.println("position(起始位置):" + buffer.position());

       System.out.println("--------------------------------------------------------");
       // 向缓存中存数据 put();
       buffer.put("hello world!".getBytes());

       System.out.println("capacity(缓存大小):" + buffer.capacity());
       System.out.println("limit(限制):" + buffer.limit());
       System.out.println("position(起始位置):" + buffer.position());

       System.out.println("--------------------------------------------------------");

       //flip() 方法切换到读的状态
       buffer.flip();

       System.out.println("capacity(缓存大小):" + buffer.capacity());
       System.out.println("limit(限制):" + buffer.limit());
       System.out.println("position(起始位置):" + buffer.position());
       System.out.println("--------------------------------------------------------");

       // 从缓存中取数据 get()
       //byte b = buffer.get();
       byte[] dst = new byte[buffer.limit()];
       buffer.get(dst);
       System.out.println(new String(dst));

       System.out.println("capacity(缓存大小):" + buffer.capacity());
       System.out.println("limit(限制):" + buffer.limit());
       System.out.println("position(起始位置):" + buffer.position());
       System.out.println("--------------------------------------------------------");

       // rewind() 重写 其起始位置从零开始
       buffer.rewind();
       System.out.println("capacity(缓存大小):" + buffer.capacity());
       System.out.println("limit(限制):" + buffer.limit());
       System.out.println("position(起始位置):" + buffer.position());
       System.out.println("--------------------------------------------------------");

       //clear() 清空缓存 限制增大 limit = capacity
       buffer.clear();
       System.out.println("capacity(缓存大小):" + buffer.capacity());
       System.out.println("limit(限制):" + buffer.limit());
       System.out.println("position(起始位置):" + buffer.position());
       System.out.println((char) buffer.get());
       System.out.println("--------------------------------------------------------");

   }

6. Marquer le paramètre et les autres méthodes du cache NIO_Buffer_

/**
     * 测试标记
     */

    @Test

    public void test2() {
        // capacity 分配缓存大小
        int capacity = 1024;
        ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);

        byteBuffer.put("Hello world!".getBytes());
        //flip() 方法切换到读的状态
        byteBuffer.flip();

        byte[] b = new byte[2];
        byteBuffer.get(b);
        System.out.println(new String(b));
        System.out.println("--------------------------------------------------------");


        System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
        System.out.println("limit(限制):" + byteBuffer.limit());
        System.out.println("position(起始位置):" + byteBuffer.position());
        // mark()做标记
        byteBuffer.mark();
        byteBuffer.get(b);

        System.out.println(new String(b));
        System.out.println("--------------------------------------------------------");


        System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
        System.out.println("limit(限制):" + byteBuffer.limit());
        System.out.println("position(起始位置):" + byteBuffer.position());
        // reset()回到mark标记的位置  Invariants: mark <= position <= limit <= capacity
        byteBuffer.reset();

        System.out.println("--------------------------------------------------------");

        System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
        System.out.println("limit(限制):" + byteBuffer.limit());
        System.out.println("position(起始位置):" + byteBuffer.position());


    }
    

7. NIO_Buffer_ cache direct et cache indirect

/**
  * 直接缓存区
  */
 @Test
 public void test3(){
     // 分配直接缓存区

     ByteBuffer buf = ByteBuffer.allocateDirect(1024);
     System.out.println("capacity(缓存大小):" + buf.capacity());
     System.out.println("limit(限制):" + buf.limit());
     System.out.println("position(起始位置):" + buf.position());

     System.out.println("是否为直接缓存区:" + buf.isDirect());
 }

8. Type et méthode de copie du canal NIO_Buffer_


 @Test
    /**
     * 利用通道channel进行文件复制
     */
    public void test4(){
        FileInputStream fin = null;
        FileOutputStream fout = null;

        FileChannel finChannel = null;
        FileChannel foutChannel = null;

        try {
            fin = new FileInputStream("3.jpg");
            fout = new FileOutputStream("4.jpg");
            // 获得通道
            finChannel = fin.getChannel();
            foutChannel = fout.getChannel();
            // 获得缓存
            ByteBuffer buffer = ByteBuffer.allocate(1024);//反复读3.jpg的字节到缓存 如果=1 即为读完

            while(finChannel.read(buffer)!=-1){
                //position定位到开头以便从缓存中获取数据
                buffer.flip();
                // 将缓存数据写入通道
                foutChannel.write(buffer);
                //清空缓存position定位到开头以便下次读通道读字节
                buffer.clear();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
             // 关闭通道
            try {
                if(finChannel!=null) finChannel.close();
                if(foutChannel!=null) foutChannel.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Test
    /**
     * JDK1.7之后获得的通道的方法
     */
    public void test5(){

        FileChannel fin = null;
        FileChannel fout = null;

        try {
            fin = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.READ);
            fout = FileChannel.open(Paths.get("5.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);

            // 创建缓存
            MappedByteBuffer finmap = fin.map(FileChannel.MapMode.READ_ONLY,0,fin.size());
            MappedByteBuffer outmap = fout.map(FileChannel.MapMode.READ_WRITE,0,fin.size());
            //获得3.jpg字节

            byte[] dst = new byte[finmap.limit()];
            finmap.get(dst);
            // 把字节放入缓存
            outmap.put(dst);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(fin != null) fin.close();
                if(fout != null) fin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * JDK1.7之后的获取通道方法
     * 通道间直接缓存交换数据
     * transferFrom()
     * transferTo()
     */
    @Test
    public void test6(){


        FileChannel fin = null;
        FileChannel fout = null;

        try {
            fin = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.READ);
            fout = FileChannel.open(Paths.get("6.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);

            // 创建缓存
           fin.transferTo(0,fin.size(),fout);
           fout.transferFrom(fin,0,fin.size());


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(fin != null) fin.close();
                if(fout != null) fin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

9. Dispersion et agrégation de INO_Buffer

/**
     * 分散和聚集
     */
    @Test
    public void test7() throws Exception {

        // 获得通道

        FileChannel channel = new RandomAccessFile("src/edu/xalead/TestBuffer.java",
                                                   "rw").getChannel();
        // 创建缓存
        ByteBuffer buffer1 = ByteBuffer.allocate(1024);
        ByteBuffer buffer2 = ByteBuffer.allocate(1024);
        ByteBuffer buffer3 = ByteBuffer.allocate(1024);
        ByteBuffer buffer4 = ByteBuffer.allocate(1024);
        ByteBuffer buffer5 = ByteBuffer.allocate(1024);
        ByteBuffer buffer6 = ByteBuffer.allocate(1024);
        ByteBuffer buffer7 = ByteBuffer.allocate(1024);
        ByteBuffer buffer8 = ByteBuffer.allocate(1024);
        ByteBuffer buffer9 = ByteBuffer.allocate(1024);
        ByteBuffer buffer10 = ByteBuffer.allocate(1024);

        // 分散读取
        ByteBuffer[] buffers = {buffer1,buffer2,buffer3,buffer4, buffer5, buffer6, buffer7, buffer8,buffer9,buffer10};

        channel.read(buffers);

        for(ByteBuffer buffer: buffers){

            System.out.println(new String(buffer.array(),0,buffer.limit()));
            System.out.println("-----------------------------------------------------------");
        }
        //聚集写入
        FileChannel channel1 = new RandomAccessFile("T.java","rw").getChannel();
        // 把buffer的position恢复到起始位置

        for(ByteBuffer buffer:buffers){
            buffer.flip();
        }
        channel1.write(buffers);
        channel.close();
        channel1.close();

    }
  

10 Résumé NIO

Tampon

Type de cache (utilisé pour mettre en cache différents types de données, en omettant la conversion de type)

  • ByteBuffer
  • IntBuffer
  • ShortBuffer
  • LongBuffer
  • CharBuffer
  • FloatBuffer
  • DoubleBuffer

Deux méthodes principales de mise en cache et d'accès aux données

  • put () enregistrer les données dans le cache
  • get () récupère les données du cache

Quatre paramètres dans le cache

  • capacité
  • limite
  • position
  • marque

Tampon direct et tampon indirect:

Tampon non direct: allouer le tampon par la méthode allocate () et établir le tampon dans la mémoire de la JVM
Tampon direct: allouer le tampon direct par la méthode allocateDirect () et établir le tampon dans la mémoire physique. Peut améliorer l'efficacité

  1. Le tampon d'octets est direct ou indirect. S'il s'agit d'un tampon d'octets direct, la machine virtuelle Java fera de son mieux pour effectuer des opérations d'E / S natives directement sur ce tampon. C'est-à-dire qu'avant chaque (ou après) une opération d'E / S native du système d'exploitation sous-jacent est appelée, la machine virtuelle essaiera d'éviter de copier le contenu du tampon dans le tampon intermédiaire (ou de copier le contenu du tampon intermédiaire ).
  2. Des tampons d'octets directs peuvent être créés en appelant la méthode d'usine allocateDirect () de cette classe . Les tampons renvoyés par cette méthode coûtent généralement plus cher à allouer et désallouer que les tampons non directs. Le contenu des tampons directs peut résider en dehors du tas de récupération de place conventionnel, de sorte que leur impact sur les besoins en mémoire de l'application peut ne pas être évident. Par conséquent, il est recommandé que les tampons directs soient principalement alloués aux grands tampons persistants qui sont sensibles aux opérations d'E / S natives du système sous-jacent. En général, il est préférable d'allouer des tampons directs uniquement lorsqu'ils peuvent fournir un avantage significatif dans les performances du programme.
  3. Des tampons d'octets directs peuvent également être créés en mappant directement la zone de fichiers dans la mémoire via la méthode FileChannel map () . Cette méthode renvoie MappedByteBuffer . L'implémentation de la plate-forme Java facilite la création de tampons d'octets directs à partir du code natif via JNI. Si une instance de tampon dans ces tampons fait référence à une zone de mémoire inaccessible, tenter d'accéder à la zone ne changera pas le contenu du tampon et provoquera un lancer pendant l'accès ou à une date ultérieure Exceptions incertaines.
  4. Que le tampon d'octets soit un tampon direct ou un tampon indirect peut être déterminé en appelant sa méthode isDirect () . Cette méthode est fournie pour permettre la gestion explicite du tampon dans le code critique pour les performances.
101 articles originaux publiés · J'ai aimé 47 · Plus de 10 000 visiteurs

Je suppose que tu aimes

Origine blog.csdn.net/TONGZONGE/article/details/104453138
conseillé
Classement