NIO编程基础

IO和NIO区别:
其本质就是阻塞和非阻塞的区别。
阻塞的概念:应用程序在获取网络数据的时候,如果网络传输数据很慢,就会一直等待,直到传输完毕。
非阻塞概念:应用程序直接可以获取已经准备就绪好的数据,无需等待。
IO为同步阻塞形式,NIO为非同步阻塞形式,NIO病咩有实现异步,在JDK1.7后升级NIO库包,支持异步非阻塞同步模型NIO2.0;
IO模式:同步阻塞模式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的请求都会注册到多路复用器上,多路复用轮询到连接有IO请求时才启动一个线程进行处理。
AIO:异步非阻塞式IO,服务器实现模式为一个有效请求一个线程,客户端的IO请求都是有OS先完成了再通知服务器应用去启动线程进行处理。
同步时,应用程序会直接参与IO读写操作,并且我们的应用程序会直接阻塞到某个方法上,直到数据准备就绪,或者采用轮询的策略实时检查就绪状态,如果就绪则获取数据。
异步时,则所有的IO读写教程操作系统,与我们的应用程序无关,我们程序不需要关系IO读写,当请求系统完车了IO读写操作时,会给我们的应用程序发送通知吗,我们的应用程序直接拿走数据就可以了。
断点续传:
多线程加上文件的拼接组成的。
Buffer缓冲区的用法:
实现缓冲区的读写操作:

    @Test
    public void test01(){
        //初始化buffer容量。
        allocate = ByteBuffer.allocate(1024);
        System.out.println("=======>>>>>>缓存区可用大小:"+ allocate.limit());
        System.out.println("==========>>>>缓冲区正在操作的位置:"+ allocate.position());
        System.out.println("==========>>>>>缓存区最大的容量:"+ allocate.capacity());
        System.out.println("==========>>>>缓冲区存放数据:");
        allocate.put("1234567".getBytes());
        System.out.println("=======>>>>>>缓存区可用大小:"+ allocate.limit());
        System.out.println("==========>>>>缓冲区正在操作的位置:"+ allocate.position());
        System.out.println("==========>>>>>缓存区最大的容量:"+ allocate.capacity());
        allocate.flip();//开启读取模式

        byte [] bytes = new byte[allocate.limit()];
        allocate.get(bytes);
        System.out.println("==========>>>>>>读取的数据是:"+new String(bytes,0,bytes.length));
        System.out.println("==========>>>>>>>重复读取");
        allocate.rewind();//开启重复读取模式
        byte [] bytes1 = new byte[allocate.limit()];
        allocate.get(bytes1);
        System.out.println("==========>>>>>>读取的数据是:"+new String(bytes1,0,bytes1.length));
        System.out.println("清空缓冲区:"+allocate.clear());
        System.out.println("=======>>>>>>缓存区可用大小:"+ allocate.limit());
        System.out.println("==========>>>>缓冲区正在操作的位置:"+ allocate.position());
        System.out.println("==========>>>>>缓存区最大的容量:"+ allocate.capacity());
        System.out.println((char)allocate.get());
    }

mark和rest用法的区别:
标记:mark与重制rest:
标记是一个索引,通过Buffer中的mark()方法中一个特定的posiotion,之后可以通过reset()方法恢复搭配这个position。

 @Test
    public void  test02(){
        ByteBuffer byteBuffer =ByteBuffer.allocate(10);//初始化,Byte的容量设置为10,
        byteBuffer.put("abcdefg".getBytes());
        byteBuffer.flip();//开启读写模式
        byte [] bytes = new byte[byteBuffer.limit()];
        byteBuffer.get(bytes,0,2);
        byteBuffer.mark();//做一个标记
        System.out.println(new String (bytes,0,2));
        System.out.println(byteBuffer.position());
        System.out.println("===============>>>>>>>>>");
        byteBuffer.get(bytes,2,2);
        System.out.println(new String(bytes,0,2));
        byteBuffer.reset();//恢复到mark位置标记
        System.out.println(byteBuffer.position());
    }

缓存区分为直接缓存区和非直接缓存区:
非直接缓存区主要存存放jvm缓存区中,
直接缓存区主要存放在物理内存中。
存放在物理内存中效率比较高。
非直接缓存区更加安全。
直接字节缓冲区可以通过调用此类的 allocateDirect() 工厂方法来创建。
通道(Channel)的原理的获取:
通道表示打开到IO设备(例如:文件,套接字)的连接,若需要使用NIO系统,需要获取用于连接IO设备的通道以及用于容纳数据的缓存区,然后操作缓存区,对数据进行处理,Channel负责传输,Buffer赋值存储,通道是有Java.io.channels 包定义的Channle表示IO源与目标打开的连接。Channle类似于传统的流,只不过Channel本身不能直接访问数据,Channle只能与Buffer进行交互。
Java.nio.channels.Channel接口:

	FileChannel:
	
	SocketChannel:
	ServerSocketChannel:
	DatagramChannel:

获取通道:
1.Java针对支持通道的类提供了getChannel()方法
本地io:
FileInputStream/FileOutPutStream()
RandomAccessFile()
网络IO :
Socket:
ServerSocket:
DataGramSocket:
2.在JDK1.7中NIO.2提供了针对各个通道提供了静态的方法open()
3.在JDK1.7中NIO.2 中Files工具类的newByteChannel().

@Test
    public void test03()throws Exception{
        //读入流
        FileInputStream fileInputStream = new FileInputStream("/Users/yantianpeng/Desktop/11.png");
        //写入流
        FileOutputStream fileOutputStream = new FileOutputStream("/Users/yantianpeng/Desktop/2.png");
        //创建读入通道
        FileChannel channel = fileInputStream.getChannel();
        //创建写入通道
        FileChannel channel1 = fileOutputStream.getChannel();//非缓存区读取操作
        //分配指定大小缓存区
        ByteBuffer allocate = ByteBuffer.allocate(1024);
        while (channel.read(allocate)!=-1){
            //开启读写模式
            allocate.flip();
            channel1.write(allocate);
            allocate.clear();//buffer必须clear
        }
        channel1.close();
        channel.close();
        fileOutputStream.close();
        fileOutputStream.close();
    }

分散读取:将通道中的数据分散到多个缓冲区中。
聚集写入:将多个缓存区的数据聚集到通道中。

    /**
     * 非散读取:将通道中的数据分散到多个缓冲区中。
     * 聚集写入:将多个缓存区的数据聚集到通道中。
     */
@Test
    public void test05() throws  Exception{
        //随机访问
        RandomAccessFile randomAccessFile = new RandomAccessFile("/Users/yantianpeng/Desktop/1.txt", "rw");
        //获取通道
        FileChannel channel = randomAccessFile.getChannel();
        //分配指定大小指定缓存区
        ByteBuffer allocate1 = ByteBuffer.allocate(100);
        ByteBuffer allocate2 = ByteBuffer.allocate(1024);
        ByteBuffer [] bufs= {allocate1,allocate2};
        channel.read(bufs);
        for (ByteBuffer byteBuffer: bufs) {
                byteBuffer.flip();//开启读写模式
        }
        String string =new java.lang.String(bufs[0].array(),0,bufs[0].limit());
        System.out.println(string);
        System.out.println("=======================================");
        System.out.println(new String(bufs[1].array(),1,bufs[1].limit()));
        System.out.println("==========>>>>>>>>>>>聚集读写操作");
        RandomAccessFile randomAccessFile1 = new RandomAccessFile("/Users/yantianpeng/Desktop/2.txt ", "rw");
        //获取通道
        FileChannel channel1 = randomAccessFile1.getChannel();
        channel1.write(bufs);
        randomAccessFile1.close();
        randomAccessFile.close();
    }

你可能感兴趣的:(Java)