JAVA基础-IO

1,IO 概念

IO 通常表示计算机与外界数据的输入与输出。I/O 流:IO流又叫输入输出流 ,输入和输出均是以内存作为参照物

分类:

1)按照流的方向

以内存为参考物,往内存中去,叫做输入,从内存中出来,叫做输出。

2)按照读取数据方式

字节流,一次读取一个字节 byte
字符流,一次读取一个字符,具体几个字节取决于编码,只能处理文本文件。

3)按功能

节点流:可以从一个特定数据源读写数据,如 FileInputStream, FileReader
处理流(包装流):链接已存在的流之上,为程序停工更为强大的读写功能。处理流只需要关闭自己,内部的流不用关。

2,BIO

1,四大家族:

  • java.io.InputStream 字节输入流
  • java.io.OutputStream 字节输出流
  • java.io.Reader 字符输入流
  • java.io.Writer 字符输出流

2,IO 流特征

1)所有的流都实现了 java.io.Colseable接口,都是可关闭的,都有close()方法. 流毕竟是一个管道,这个是内存和硬盘之间的通道,养成一个好习惯,用完流将其关闭
2)所有的输出流都实现了 java.io.Flushable接口,都是可刷新的,都有flush()方法,这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。如果没有flush()可能会导致数据丢失.
3)在java中只要"类名"以Stream结尾的都是字节流。以"Reader/Writer"结尾的都是字符流

3,16个流需要掌握

1)文件专属

java.io.FileinputStream (用得最多)
/**
 * FileInputStream
 * 文件字节输入流,万能的,任何类型的文件都可以采用这个流来读
 * 字节的方式,完成输入的操作,完成读的操作(硬盘 —> 内存)
 *
 * 方法:
 * read() 读取一个字节,返回的是读取到的内容的 int 表示,返回 -1 表示没有读到。
 * read(byte[] b) 读取一个指定数组大小的内容,将读取内容放到 byte 数组中。返回 -1 说明没有读取到任何内容。
 * read(byte[] b, int off, int len) 读取 len 长度的字节,从数组的 off 位置开始填充数组
 * */
@Test
public void FileInputStream() throws IOException {
    FileInputStream fis = new FileInputStream("D:\\gaox\\files\\test\\io_demo\\fileInputStream.txt");

    byte[] by = new byte[4];
    int length;
    while((length = fis.read(by)) != -1){
        System.out.println(new String(by, 0, length));
    }
    fis.close();
}
java.io.FileOutputStream (用得最多)
/**
 * FileOutputStream
 * 文件字节输出流,负责写,从内存到硬盘
 * 构造方法:
 * FileOutputStream(String name, boolean append)  第二个参数表示追加。如果根据文件路径找不到文件,就会自己创建一个文件
 *
 * 方法:
 * write(int) 写入一个数字
 * write(byte[] c) 写入一个字节数组
 * <!---->write(byte[] c, int off, int len) 从数组 c 的 off 位置开始写入 len 个字节
 * flush() 刷新
 * */
@Test
public void FileOutputStream() throws IOException {
    FileOutputStream fos = new FileOutputStream("D:\\gaox\\files\\test\\io_demo\\fileOutputStream.txt");
    fos.write("yanqishiwode".getBytes(), 1, 10);
    fos.flush();
    fos.close();
}
java.io.FileReader
/**
 * FileReader
 * 文件字符输入流,以字符 char 为单位,只能读文本
 *
 * 方法:
 * getEncoding():获取编码
 * read():读取一个字符,返回 int 类型,可以强转成 char, -1 表示没读到
 * read(char[] c):读取字符数组长度的字符,然后填充到数组 c 中, -1 表示没读到,返回值为实际读的数据
 * read(char[] c, int off, int len) 读取 len 长度的字符,放到从 off 开始的数组 c 中,-1表示没读到返回值为实际读到的数据
 * */
@Test
public void FileReader() throws IOException {
    FileReader fr = new FileReader("D:\\gaox\\files\\test\\io_demo\\fileReader.txt");
    System.out.println((char)fr.read());
    System.out.println(fr.read());

    char[] chars = new char[10];
    fr.read(chars);
    System.out.println(chars);

    //读取部分,chars 数组其他位置仍然是上面读取的内容
    fr.read(chars, 4, 3);
    System.out.println(chars);

    int len;
    while((len = fr.read(chars)) != -1){
        System.out.println(len);
    }

    fr.close();
}
java.io.FileWriter
/**
 * FileWriter
 * 文件字符输出流,以字符 char 为单位
 *
 * 方法:
 * write():输出一个字符
 * write(char[] c):输出整个字符数组
 * write(char[] c, int off, int len):输入数组 c 中,从 off 开始共计 len 长度的字符
 * write(String s):输出字符串
 * write(String s, int off, int len):输出字符串的一部分
 * flush() 刷新
 * */
@Test
public void fileWriter() throws IOException {
    FileWriter fw = new FileWriter("D:\\gaox\\files\\test\\io_demo\\fileWriter.txt", true);
    fw.write(49);
    char[] chr = new char[]{'张','非','又','要','大','人','了'};
    fw.write(chr);
    fw.write(chr, 1, 3);

    fw.write("张三");
    fw.write("woaiyanqi", 3, 5);

    fw.flush();
    fw.close();
}

2)转换流 (将字节流转换成字符流)

InputStreamReader
/**
 * InputStreamReader
 * 输入转换流:将字节流转换为字符流
 *
 * 构造方法
 * InputStreamReader(InputStream in); 入参一个字节流,返回一个 inputStreamReader 转换流,该流是字符流
 *
 * read 三个 read 方法跟 reader 保持一致
 *
 *
 * */
@Test
public void InputStreamReader() throws IOException {
    InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\gaox\\files\\test\\io_demo\\fileInputReader.txt"));
    System.out.println((char)isr.read());

    char[] chr = new char[10];
    System.out.println(isr.read(chr));
    System.out.println(chr);

    chr = new char[10];
    System.out.println(isr.read(chr, 3,7));
    System.out.println(chr);

    isr.close();
}
outputStreamWriter
/**
   * outputStreamWriter
   * 输出转换流
   *
   * write 五个方法与 fileWriter 五个 write 方法一致
   * */
  @Test
  public void outputStreamWriter() throws IOException {
      OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\gaox\\files\\test\\io_demo\\outputStreamWriter.txt", true));
      //osw.write
      osw.write(49);

      osw.write(new char[]{'y','a','n','q','i'});

      osw.write("不服来战");

      osw.write(new char[]{'y','a','n','q','i'}, 1, 3);

      osw.write("hello world", 1, 3);

      osw.flush();
      osw.close();
  }

3)缓冲流专属: 缓冲流相比普通的流,多出一个缓冲区,可以读取比规定的多的数据,减少 io 次数,这类流构造方法都有个参数规定缓冲区大小

BufferedReader
/**
   * BufferedReader
   * 缓冲输入字符流
   *
   * 构造方法:
   * BufferedReader(Reader r, int size)  size 缓冲区大小
   *
   * 方法:
   * read 常规三个方法
   * readLine() 读一行
   * */
  @Test
  public void bufferedReader() throws IOException {
      BufferedReader br = new BufferedReader(new FileReader("D:\\gaox\\files\\test\\io_demo\\bufferedReader.txt"),1);
      System.out.println( (char)br.read());

      char[] chr = new char[10];
      br.read(chr);
      System.out.println(chr);

      chr = new char[10];
      br.read(chr, 1, 5);
      System.out.println(chr);

      String s = br.readLine();
      System.out.println(s);
      br.close();
  }
bufferedWriter
 /**
     * bufferedWriter
     * 缓冲字符输出流
     *
     * 构造方法:
     * BufferedWriter(Writer out)
     *
     * 方法:
     * write 五个常规方法
     * newLine() 创建新的一行
     *
     * */
    @Test
    public void bufferedWriter() throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\gaox\\files\\test\\io_demo\\bufferedWriter.txt"));
        bw.write(49);
        bw.write(new char[]{'1','2'});
        bw.newLine();
        bw.write("woaiyanqi");
        bw.flush();
        bw.close();
    }
BufferedInputStream
/**
 * BufferedInputStream
 * 字节缓冲输入流
 *
 * 构造方法:
 * BufferedInputStream(InputStream i);
 *
 * 方法:
 * read() 的三个方法
 * */
@Test
public void bufferedInputStream() throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\gaox\\files\\test\\io_demo\\bufferInputStream.txt"));
    System.out.println( bis.read() );

    byte[] b = new byte[10];
    bis.read(b);
    System.out.println(b);

    bis.read(b, 1, 9);
    System.out.println(b);
    bis.close();
}
BufferedOutputStream
/**
 * BufferedOutputStream
 *
 * 构造方法
 * BufferedOutputStream(OutputStream os)
 *
 * 方法
 * write() 三个方法
 * */
@Test
public void bufferedOutputStream() throws IOException {
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\gaox\\files\\test\\io_demo\\bufferedOutputStream.txt"));
    bos.write(49);

    String str = "wohao稀饭ya#@  &*qia";

    bos.write(str.getBytes());
    bos.write(str.getBytes(), 1, 10);
    bos.flush();
    bos.close();
}

4)数据流

DataOutputStream
/**
 * DataOutputStream
 * 数据输出流
 *
 * 构造方法
 * DataOutputStream(OutputStream os)
 *
 * 方法:
 * write() 三件套
 * writeInt() 等八大类型
 * */
@Test
public void dataOutputStream() throws IOException {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("D:\\gaox\\files\\test\\io_demo\\dataInputStream.txt"));
    dos.writeChar('燕');
    dos.writeInt(112);
    dos.writeDouble('燕');
    dos.flush();
    dos.close();
}
DataInputStream
/**
 * DataInputStream
 * 数据输入流:只能读 DataOutputStream() 写入的数据,并且需要知道顺序
 *
 * 构造方法:
 * DataInputStream(InputStream is)
 *
 * 方法:
 * read() 三件套
 * readInt() 等八大类型
 * */
@Test
public void dataInputStream() throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream("D:\\gaox\\files\\test\\io_demo\\dataInputStream.txt"));
    System.out.println( dis.readChar() );
    System.out.println(dis.readInt());
    System.out.println(dis.readDouble());
    dis.close();
}

5)标准输出流

PrintStream
/**
 * printStream
 * 标准输出流
 *
 * System.out、System.err 等返回的就是 printStream
 * */
@Test
public void printStream() throws FileNotFoundException {

    //默认输出到控制台
    PrintStream out = System.out;
    out.println("yanqi");
    out.println("nidei");
    out.println("shenmedeganh");

    //输出到日志去
    PrintStream ps = new PrintStream(new FileOutputStream("D:\\gaox\\files\\test\\io_demo\\log.txt"));
    System.setOut(ps);
    ps.println("张三");
    System.out.println("你跑哪去了");
}
PrintWriter 不知道咋用

6)对象专属流

ObjectOutputStream
/**
 * ObjectOutputStream
 * 对象输出流,配合序列化
 * */
@Test
public void objectOutputStream() throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\gaox\\files\\test\\io_demo\\objectOutputStream.txt"));
    oos.writeObject(new Cat("yanqi", 25, "white"));
    oos.writeObject(new Cat("yanqi", 26, "white"));
    oos.writeObject(new Cat("yanqi", 27, "white"));
    oos.writeObject(new Cat("yanqi", 28, "white"));
    oos.writeObject("张三");
    oos.writeObject(new Cat("yanqi", 29, "white"));
    oos.flush();
    oos.close();
}
ObjectInputStream
/**
 * ObjectInputStream
 * 对象输入流,配合序列化
 * */
@Test
public void ObjectInputStream() throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\gaox\\files\\test\\io_demo\\objectOutputStream.txt"));
    System.out.println(ois.readObject());
    System.out.println(ois.readObject());
    System.out.println(ois.readObject());
    System.out.println(ois.readObject());
    System.out.println(ois.readObject());
    System.out.println(ois.readObject());
    ois.close();
}

4,文件操作 demo

字节流复制文件
/**
 * 字节流复制文件
 * */
@Test
public void fileCopy() {
    try(
        //卸载这里,会自动关闭流
        FileInputStream fis = new FileInputStream("D:\\gaox\\files\\test\\io_demo\\bizhi.rar");
        FileOutputStream fos = new FileOutputStream("D:\\gaox\\files\\test\\copy_io_demo\\bizhi.rar")
    ){
        byte[] byt = new byte[1024];
        int len;
        while( (len = fis.read(byt)) != -1 ){
            //这里因为最后可能数组都不满,所以每次只需要将有数据的写入文件就好了
            fos.write(byt, 0, len);
        }
        fos.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
字符流复制文件:只能复制文本
/**
 * 字符流复制文件:只能复制文本
 * */
@Test
public void copyFileByChar(){
    try( FileReader fr = new FileReader("D:\\gaox\\files\\test\\io_demo\\catalina.out");
         FileWriter fw = new FileWriter("D:\\gaox\\files\\test\\copy_io_demo\\catalina.txt")
    ){
        char[] chr = new char[10];
        int len;
        while( (len = fr.read(chr)) != -1 ){
            fw.write(chr, 0, len);
        }
        fw.flush();
    }catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

5,压缩流

ZipInputStream,ZipOutputStream,ZipFile,ZipEntry 等。

压缩流 demo
/**
 * ZipOutputStream
 * 压缩流:单个文件压缩
 * */
@Test
public void zipFile() throws IOException {

    //要压缩的文件
    File file = new File("D:\\gaox\\files\\test\\io_demo\\catalina.out");
    //压缩后的压缩包
    File zipFile = new File("D:\\gaox\\files\\test\\io_demo\\catalina.zip");

    FileInputStream fs = new FileInputStream(file);
    ZipInputStream zis = new ZipInputStream(fs);
    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));

    zos.putNextEntry(new ZipEntry(file.getName()));

    byte[] byt = new byte[1024];
    int len;
    while( (len = fs.read(byt)) != -1 ){
        zos.write(byt, 0, len);
    }
    zos.close();
    zis.close();
}

/**
 * ZipOutputStream
 * 压缩流:文件夹压缩
 * */
@Test
public void zipFiles() throws IOException {
    //要压缩的文件夹
    File file = new File("D:\\gaox\\files\\test\\io_demo");
    //压缩后的压缩包
    File zipFile = new File("D:\\gaox\\files\\test\\copy_io_demo\\io_demo.zip");
    
    //定义文件输入流
    InputStream is;
    
    //定义输出压缩流
    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
    zos.setComment("yanqi");

    recursionZip(zos, file, "");
    zos.close();
}

//压缩方法抽出
private void recursionZip(ZipOutputStream zos, File file, String baseDir) throws IOException {
    byte[] byt = new byte[1024];
    int len;

    if(file.isDirectory()){
        //如果是文件夹,获取文件夹下所有文件
        File[] files = file.listFiles();
        for(File item : files){
            recursionZip(zos, item, baseDir + File.separator + file.getName());
        }
    }else{
        //对文件做压缩处理
        FileInputStream is = new FileInputStream(file);
        zos.putNextEntry(new ZipEntry(baseDir + File.separator + file.getName()));

        while(( len = is.read(byt)) != -1){
            zos.write(byt, 0, len);
        }
        is.close();

    }
}

/**
 * 解压缩
 * ZipFile
 * */
@Test
public void unzip() throws IOException {

    //压缩包
    File inFile = new File("D:\\gaox\\files\\test\\copy_io_demo\\io_demo.zip");
    ZipFile zipFile = new ZipFile(inFile);

    //解压后的文件路径
    String path = inFile.getParent();

    //压缩输入流
    ZipInputStream zis = new ZipInputStream(new FileInputStream(inFile));

    ZipEntry entity;
    while( (entity = zis.getNextEntry()) != null ){
        System.out.println("解压缩:" + entity.getName());

        File outFile = new File(path + File.separator + entity.getName());
        if( !outFile.getParentFile().exists() ){
            outFile.getParentFile().mkdir();
        }
        outFile.createNewFile();

        InputStream is = zipFile.getInputStream(entity);
        FileOutputStream fos = new FileOutputStream(outFile);

        byte[] byt = new byte[1024];
        int len;
        while( (len = is.read(byt)) != -1 ){
            fos.write(byt, 0, len);
        }
        is.close();
        fos.close();
    }
}

3,NIO

1,NIO 简介

  nio:new io,也称为非阻塞 io。与原来的 io 有同样的作用和目的,但是使用方式完全不同。

  NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。NIO可以理解为非阻塞IO,传统的IO的read和write只能阻塞执行,线程在读写IO期间不能干其他事情,比如调用socket.read()时,如果服务器一直没有数据传输过来,线程就一直阻塞,而NIO中可以配置socket为非阻塞模式

2,NIO 特点

1)NIO相关类都被放在java.nio包及子包下,并且对原java.io包中的很多类进行改写。

2)NIO有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)

3)Java NlO的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。

4)通俗理解:NIO是可以做到用一个线程来处理多个操作的。假设有1000个请求过来,根据实际情况,可以分配20或者80个线程来处理。不像之前的阻塞IO那样,非得分配1000个。

3,nio 和 io 比较

1)BIO以流的方式处理数据,而NIO以块的方式处理数据,块I/O的效率比流IO高很多

2)BIO是阻塞的,NIO则是非阻塞的(Java NIO 的非阻塞,是相对于连接的非阻塞,而不是指方法调用时的非阻塞)

3)BlO基于字节流和字符流进行操作,而NIO基于Channel(通道)和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择器)用于监听多个通道的事件(比如:连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道

4,NIO 三要素

1),Buffer 缓冲区

  java.nio.Buffer 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。相比较直接对数组的操作,Buffer APl更加容易操作和管理。

  nio 面向块,这个块就是 Buffer

2). Channel 通道
  通道(Channel):由 java.nio.channels 包定义 的。Channel 表示 IO 源与目标打开的连接。 Channel 类似于传统的“流”。只不过 Channel 本身不能直接访问数据,Channel 只能与 Buffer 进行交互

3),Selector 选择器
  选择器(Selector)是SelectableChannle对象的多路复用器,Selector可以同时监控多个SelectableChannel的IO状况,也就是说,利用Selector可使一个单独的线程管理多个Channel。Selector是非阻塞IO的核心

5,NIO demo

public class DemoMain {

    /**
     * nio 写本地文件
     * */
    @Test
    public void write() throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\gaox\\files\\日志\\copy.txt");
        FileChannel channel = fos.getChannel();

        ByteBuffer buf = ByteBuffer.allocate(1024);
        buf.put("yanqinidenalipaowl来两个中文ogaodingnil".getBytes());
        buf.flip();
        channel.write(buf);
        buf.clear();
        channel.close();
    }

    /**
     * nio 读本第文件
     * */
    @Test
    public void read() throws IOException {
        FileInputStream fis = new FileInputStream("D:\\gaox\\files\\日志\\test.log");
        FileChannel chl = fis.getChannel();

        int bufLength = 1024;
        ByteBuffer buf = ByteBuffer.allocate(bufLength);
        byte[] bytes = new byte[bufLength];

        int read;
        while( (read = chl.read(buf)) != -1){
            buf.flip();
            buf.get(bytes, 0 , read);
            System.out.println(new String(bytes));
            buf.clear();
        }
        chl.close();
    }

    /**
     * 使用 buffer复制
     * */
    @Test
    public void bufferCopy() throws IOException {
        FileChannel fic = new FileInputStream("D:\\gaox\\files\\日志\\catalina1231231241231312311312414.out").getChannel();
        FileChannel foc = new FileOutputStream("D:\\gaox\\files\\日志\\bufferCopy.out").getChannel();

        ByteBuffer buf = ByteBuffer.allocate(1024);
        while(fic.read(buf) != -1){
            buf.flip();
            foc.write(buf);
            buf.clear();
        }
        fic.close();
        foc.close();
    }

    /**
     * transferFrom 复制
     * */
    @Test
    public void transferFrom() throws IOException {
        FileChannel fic = new FileInputStream("D:\\gaox\\files\\日志\\catalina1231231241231312311312414.out").getChannel();
        FileChannel foc = new FileOutputStream("D:\\gaox\\files\\日志\\bufferCopy1.out").getChannel();

        foc.transferFrom(fic, fic.position(), fic.size());
        fic.close();
        foc.close();
    }

    /**
     * transferTo 复制
     * */
    @Test
    public void transferTo() throws IOException {
        FileChannel fic = new FileInputStream("D:\\mySoftWare\\jdk-17_windows-x64_bin.zip").getChannel();
        FileChannel foc = new FileOutputStream("D:\\mySoftWare\\jdk-17_windows-x64_bi1n1.zip").getChannel();

        long l = fic.transferTo(fic.position(), fic.size(), foc);
        System.out.println("传输完成!");
        fic.close();
        foc.close();
    }

    /**
     * 案例6-分散 (Scatter) 和聚集 (Gather)
     * */
    @Test
    public void test() throws IOException{
        RandomAccessFile raf1 = new RandomAccessFile("D:\\gaox\\files\\日志\\catalina1231231241231312311312414.out", "rw");
        //1. 获取通道
        FileChannel channel1 = raf1.getChannel();

        //2. 分配指定大小的缓冲区
        ByteBuffer buf1 = ByteBuffer.allocate(100);
        ByteBuffer buf2 = ByteBuffer.allocate(1024);

        //3. 分散读取
        ByteBuffer[] bufs = {buf1, buf2};
        channel1.read(bufs);

        for (ByteBuffer byteBuffer : bufs) {
            byteBuffer.flip();
        }

        System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
        System.out.println("-----------------");
        System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));

        //4. 聚集写入
        RandomAccessFile raf2 = new RandomAccessFile("D:\\gaox\\files\\日志\\bufferCopy3.out", "rw");
        FileChannel channel2 = raf2.getChannel();

        channel2.write(bufs);
    }

}

6,I/O 多路复用技术

  在传统的IO编程中,每个socket连接都需要一个线程或进程来处理,这样就会导致系统资源的浪费和性能问题。而IO多路复用则可以通过一个线程或进程来同时管理多个socket连接,并且可以同时处理多个连接上的IO事件。

  常用的IO多路复用技术有select、poll、epoll等。

  以select为例,当一个进程调用select函数时,它会将多个文件描述符注册到一个监控集合中,并设置监听事件类型(如可读、可写、异常等)。然后,select函数会阻塞进程,直到监控集合中的任意一个文件描述符发生了监听事件(读、写)。此时,select函数就会返回,并告诉进程哪些文件描述符有事件发生,进程可以根据返回值来处理相应的IO事件。

7,Reactor 模式

  Reactor 设计模式就是基于建立连接与具体服务之间线程分离的模式。在 Reactor 模式中,会有一个线程负责与所有客户端建立连接,这个线程通常称之为 Reactor。然后在建立连接之后,Reactor 线程 会使用其它线程(可以有多个)来处理与每一个客户端之间的数据传输,这个(些)线程通常称之为 Handler

4,AIO

1,简介

AIO,异步非阻塞 IO,又称 NIO2.0,最大的一个特性就是异步能力,这种能力对socket与文件I/O都起作用。AIO其实是一种在读写操作结束之前允许进行其他操作的I/O处理。

2,AIO demo

/**
 *
 *   AsynchronousSocketChannel
 * ​ AsynchronousServerSocketChannel
 * ​ AsynchronousFileChannel
 * ​ AsynchronousDatagramChannel
 * */
public class AioDemo {

    @Test
    public void test() throws IOException, ExecutionException, InterruptedException {
        AsynchronousFileChannel channel = open(Paths.get("D:\\gaox\\files\\模型\\科艺楼.安装模型 - 副本.zip"), StandardOpenOption.READ);

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024 * 1024);
        Future<Integer> read = channel.read(byteBuffer, 0);

        System.out.println("读了,但是不知道有没有读出来!");
        read.get();
        byteBuffer.flip();
        System.out.println("读出来了:" + byteBuffer.get());
    }


}

5,参考文献

JAVA-IO详解

java之NIO简介

Java NIO 中的非阻塞究竟体现在哪里

posted @ 2024-02-19 10:36  primaryC  阅读(4)  评论(0编辑  收藏  举报