NIO-编程实战(一)

简介: NIO-编程实战(一)

一、NIO总共分为三大部分:

1、缓冲区:Buffer是所有的xxxBuffer类的父类,MappedByyteBuffer:映射的类,主要是映射系统中的内存。

缓存区分为两种,一种是直接缓冲区,另一种是非缓冲区。

缓存区有Buffer,ByteBuffer,LongBuffer,IntegerBuffer,FloatBuffer,DoubleBuffer。

非直接缓冲区主要存放在jvm缓存区中来拷贝

直接缓冲区--存在物理内存中。

2、选择器:poll模型是windows里面的,epoll是linux系统中的,select,kqueue是操作系统的整个selector在构建的时候不是由java来构建的,而是由java语言调用c语言来是实现的,它的底层是系统的底层。

3、通道:NIO最关联的就是通道,而通道要和选择器的事件进行绑定。

二、关于Buffer的代码如下:

1、创建ByteBuffer的对象,这里不是new的,而是创建该对象时要分配内存:allocate代表分配一块内存空间,将ByteBuffer的对象指向内存空间里面去。单位是字节,代码如下:

  1. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  2. System.out.println("position:"+byteBuffer.position());
  3. System.out.println("limit:"+byteBuffer.limit());
  4. System.out.println("capacity:"+byteBuffer.capacity());
  5. System.out.println("往bytebuffer里存放数据。。。");
  6. byteBuffer.put("A23abc一二三".getBytes());
  7. System.out.println("position:"+byteBuffer.position());
  8. System.out.println("limit:"+byteBuffer.limit());
  9. System.out.println("capacity:"+byteBuffer.capacity());

运行的结果如下:往缓存区里放数据只会导致position的大小会变,其他的不会变。

2、如何从缓存区中读数据

  1. System.out.println("往bytebuffer里读取数据。。。");
  2. byteBuffer.flip();// 开启读取模式
  3. System.out.println("position:"+byteBuffer.position());
  4. System.out.println("limit:"+byteBuffer.limit());
  5. System.out.println("capacity:"+byteBuffer.capacity());
  6. //应用程序的一个缓存
  7. byte[] bytes = new byte[byteBuffer.limit()];
  8. //读取到缓存区中
  9. byteBuffer.get(bytes);
  10. System.out.println(newString(bytes, 0, bytes.length));

运行的结果如下:这时position置为0,limit的值和上次的position的值一样,把position的值赋给limit。一旦缓冲区的容量定下来以后,那么缓冲区的容量是不可变的。读的数据就是从0的位置到15的位置。

3、rewind方法:

  1. System.out.println("往bytebuffer里重复读取数据。。。" );
  2. byteBuffer.rewind();

  3. System.out.println("position:"+byteBuffer.position());
  4. System.out.println("limit:"+byteBuffer.limit());
  5. System.out.println("capacity:"+byteBuffer.capacity());
  6. byte[] bytes2 = new byte[byteBuffer.limit()];
  7. byteBuffer.get(bytes2);
  8. System.out.println(newString(bytes2, 0, bytes.length));

运行的结果如下:rewind:重复读取,不加这个方法会报错,因为limit后面不能再读取数据了。这个方法的意思是重复读的意思。limit不会变,但是position会变为0。

4、clear方法:调用这个方法的意思又可以再进行写的操作。

  1. System.out.println("清空缓存区。。。");
  2. byteBuffer.clear();//// 值不清空 下标清空
  3. System.out.println("position:"+byteBuffer.position());
  4. System.out.println("limit:"+byteBuffer.limit());
  5. System.out.println("capacity:"+byteBuffer.capacity());
  6. System.out.println((char) byteBuffer.get());

运行的结果如下:


小结总结:上面的缓冲区是普通的缓冲区,直接放到了jvm当中的。而缓存区是不停的再读数据,会覆盖。

5、分散读取聚集写入

可以分开去读,写是在一起写。

注意:在分配指定大小的缓冲区的时候,如果是直接缓冲区的话是直接写在内存中,不是写在jvm的工作缓存区的。如果用分散读取聚集写入的话,不能用直接的缓冲区的方式,应该用普通的方式来分配。

代码如下:

  1.        // 随机访问
  2.        RandomAccessFile raf = new RandomAccessFile("d:/abc.txt", "rw");
  3.        // 获取通信
  4.        FileChannel channel = raf.getChannel();
  5.        // 分配指定大小指定缓冲区      

  6.        //这两个缓冲区是连通的
  7.        //buf2相当于是备用缓冲区
  8.        ByteBuffer buf1 = ByteBuffer.allocate(6);
  9.        ByteBuffer buf2 = ByteBuffer.allocate(10);
  10.        // 分散读取
  11.        ByteBuffer[] bufs = {buf1, buf2};
  12.        channel.read(bufs);
  13.        for (ByteBuffer buf : bufs) {
  14.            // 切换成读模式
  15.            buf.flip();
  16.        }
  17.        System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
  18.        System.out.println("-----------------------------");
  19.        System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));
  20.        System.out.println("-----------重复读取-------------");
  21.        RandomAccessFile raf2 = new RandomAccessFile("d:/abc.txt", "rw");
  22.        // 获取通道
  23.        FileChannel channel2 = raf2.getChannel();
  24.        channel2.write(bufs);
  25.        raf2.close();
  26.        raf.close();

运行的结果如下:

关于管道的代码如下:

  1. package com.gerry.nio.demo.nio.channel;

  2. import java.io.*;  
  3. import java.nio.*;  
  4. import java.nio.channels.*;

  5. /**
  6. * 通道和流绑定
  7. * 普通的缓冲区是基于jvm的,直接缓冲区是基于内存的。
  8. */
  9. public class FileInputProgram {  
  10.    static public void main( String args[] ) throws Exception {  
  11.        FileInputStream fin = new FileInputStream("d:/abc.txt");

  12.        // 在jdk1.5之后可以通过文件的流对象获取通道
  13.        FileChannel fc = fin.getChannel();  

  14.        // 创建缓冲区
  15.        ByteBuffer buffer = ByteBuffer.allocate(1024);  

  16.        // 读取数据到缓冲区
  17.        fc.read(buffer);  

  18.        buffer.flip();  
  19.        //判断是否已经读完
  20.        while (buffer.remaining() > 0) {  
  21.            byte b = buffer.get();  
  22.            System.out.print(((char)b));  
  23.        }  

  24.        fin.close();
  25.    }  
  26. }

运行的结果如下:

  1. package com.gerry.nio.demo.nio.channel;

  2. import java.io.*;  
  3. import java.nio.*;  
  4. import java.nio.channels.*;  

  5. public class FileOutputProgram {  
  6.    static private final byte message[] = {'a','c','d','e'};

  7.    static public void main( String args[] ) throws Exception {  
  8.        FileOutputStream fout = new FileOutputStream( "e:/abc.txt");

  9.        FileChannel fc = fout.getChannel();  

  10.        ByteBuffer buffer = ByteBuffer.allocate( 1024 );  

  11.        for (int i=0; i<message.length; ++i) {
  12.            buffer.put(message[i]);
  13.        }
  14.        buffer.flip();
  15.        fc.write( buffer );

  16.        fout.flush();
  17.        fout.close();  
  18.    }  
  19. }

运行的结果如下:

总结:上面的是关于nio的缓冲区和通道中常用的方法做了一个总结,明天继续写关于nio的selector的网络通信的应用以及netty的入门。

相关文章
|
缓存 安全 Java
由浅入深Netty基础知识NIO三大组件原理实战 2
由浅入深Netty基础知识NIO三大组件原理实战
76 0
|
Java
由浅入深Netty基础知识NIO三大组件原理实战 1
由浅入深Netty基础知识NIO三大组件原理实战
103 0
|
3月前
NIO-编程实战(二)
NIO-编程实战(二)
|
2月前
|
Java Linux 应用服务中间件
【编程进阶知识】高并发场景下Bio与Nio的比较及原理示意图
本文介绍了在Linux系统上使用Tomcat部署Java应用程序时,BIO(阻塞I/O)和NIO(非阻塞I/O)在网络编程中的实现和性能差异。BIO采用传统的线程模型,每个连接请求都会创建一个新线程进行处理,导致在高并发场景下存在严重的性能瓶颈,如阻塞等待和线程创建开销大等问题。而NIO则通过事件驱动机制,利用事件注册、事件轮询器和事件通知,实现了更高效的连接管理和数据传输,避免了阻塞和多级数据复制,显著提升了系统的并发处理能力。
67 0
|
5月前
|
Java
Java中的NIO编程详解
Java中的NIO编程详解
|
5月前
|
Java
Java中的NIO编程详解
Java中的NIO编程详解
|
6月前
|
存储 监控 Java
Java中的NIO编程实践精华
Java中的NIO编程实践精华
|
6月前
|
存储 监控 Java
了解Java中的NIO编程
了解Java中的NIO编程
|
Java
Netty入门到超神系列-Java NIO零拷贝实战
这一章我们来操作一下NIO的零拷贝,这里我会先写代码样式一下传统IO数据拷贝场景下的耗时,然后再对比NIO场景下的考别耗时,通过耗时差异就能看到NIO零拷贝和传统IO拷贝的区别了。
127 0
|
缓存 Java
Java NIO实战篇:使用Socket实现报文交互
Java NIO实战篇:使用Socket实现报文交互
236 0