>  기사  >  Java  >  Java 입출력 IO, NIO, AIO 비교 분석

Java 입출력 IO, NIO, AIO 비교 분석

王林
王林앞으로
2023-05-08 23:07:071542검색

    1. Java I/O 개발의 역사

    Java 입출력 IO, NIO, AIO 비교 분석

    Java IO(Input/Output)는 Java 언어로 데이터를 읽고 쓰기 위한 일련의 클래스와 인터페이스를 제공합니다. 다양한 유형의 데이터를 작성합니다. 다음은 Java IO의 개발 역사를 간략하게 소개합니다.

    • JDK 1.0(1996) 초기 Java IO는 Blocking IO(Blocking IO)를 기반으로 바이트 스트림(InputStream, OutputStream)과 문자 스트림(Reader, Writer)만 지원했습니다. 바이오) 모델.

    • JDK 1.1(1997) JDK 1.1은 NIO(New IO) 패키지를 도입하고 버퍼 및 채널과 같은 개념을 지원하며 보다 효율적인 IO 작업 방법을 제공하고 Non-Blocking IO(NIO) 모드를 달성할 수 있었습니다.

    • JDK 1.4(2002) JDK 1.4에는 버퍼가 있는 Java NIO라고도 하는 NIO.2 API가 추가되어 더욱 강력한 파일 처리 기능과 보다 효율적인 IO 작업을 제공합니다.

    • JDK 7(2011) JDK 7은 비동기 IO 모드를 지원하고 많은 수의 동시 요청을 처리할 수 있는 AIO(비동기 IO)라고도 알려진 완료 포트가 있는 NIO.2의 향상된 버전인 NIO.2를 도입합니다. . 장점이 있습니다.

    다음은 세 가지의 차이점입니다.

    Java 입출력 IO, NIO, AIO 비교 분석

    • BIO(Blocking IO) BIO는 데이터 읽기 및 쓰기 작업에 차단 방법을 사용하는 Java의 원래 IO 모델입니다. 즉, 스레드가 IO 작업을 수행할 때 읽을 데이터가 없으면 스레드는 읽을 데이터가 있거나 타임아웃될 때까지 차단하고 대기합니다. BIO는 연결 수가 상대적으로 적고 고정되어 있지만 동시성 성능이 부족한 시나리오를 처리하는 데 적합합니다.

    • NIO(Non-blocking IO) NIO는 Java 1.4에 도입된 새로운 IO 모델입니다. 멀티플렉서(Selector) 메커니즘을 사용하여 적은 수의 스레드를 통해 동시에 여러 채널을 관리하므로 단일 스레드가 동시에 여러 채널을 처리합니다. NIO는 높은 동시성, 높은 처리량 및 높은 안정성을 갖추고 있으며 연결 수가 많고 연결 시간이 짧은 시나리오를 처리하는 데 적합합니다.

    • AIO(비동기 IO) AIO는 Java 1.7에서 지원되는 IO 모델입니다. 데이터를 읽고 쓰는 데 이벤트 중심 접근 방식을 사용하며 데이터가 콜백 함수에서 처리됩니다. NIO와 달리 AIO의 읽기 및 쓰기 작업은 비동기식이며 데이터가 준비되었는지 확인하기 위해 폴링할 필요가 없습니다. AIO는 연결 수가 많고 연결 시간이 길며 읽기 및 쓰기 작업이 많은 시나리오를 처리하는 데 적합합니다.

    2. Java IO

    2.1 소개

    Java 프로그래밍에서 IO(입력/출력) 작업은 파일 읽기 및 쓰기, 네트워크 통신 등을 포함하는 매우 일반적인 작업입니다. Java는 이러한 작업을 지원하기 위해 다양한 클래스를 제공합니다. 이 기사에서는 IO에 대한 기본 지식부터 시작하여 점차적으로 Java IO의 모든 측면을 소개하는 심층적인 내용을 다룰 것입니다.

    2.2 기본 개념

    2.2.1 입력 스트림과 출력 스트림

    Java에서는 입력 스트림(InputStream)과 출력 스트림(OutputStream)이 두 가지 중요한 추상 클래스입니다. 입력 스트림은 파일, 네트워크 연결, 파이프 등이 될 수 있는 입력 데이터의 소스를 나타냅니다. 출력 스트림은 파일, 네트워크 연결, 파이프 등이 될 수 있는 출력 데이터의 대상을 나타냅니다. 입력 스트림과 출력 스트림은 스트림 객체를 생성한 다음 해당 메서드 인터페이스를 사용하여 읽기 및 쓰기 작업을 수행하는 방식으로 비슷한 방식으로 사용됩니다.

    2.2.2 바이트 스트림과 문자 스트림

    Java의 IO 작업은 바이트 스트림과 문자 스트림의 두 가지 유형으로 나눌 수도 있습니다. 바이트 스트림은 바이트(byte) 단위로 작동하며 이미지, 오디오 등과 같은 이진 데이터를 처리하는 데 적합하고 문자 스트림은 문자(char) 단위로 작동하며 다음과 같은 텍스트 데이터를 처리하는 데 적합합니다. 텍스트 파일 등 Java에서 바이트 스트림은 주로 InputStream 및 OutputStream 클래스와 해당 하위 클래스에 의해 구현되는 반면 문자 스트림은 주로 Reader 및 Writer 클래스와 해당 하위 클래스에 의해 구현됩니다.

    2.2.3 Buffered Stream

    IO 작업을 수행할 때 자주 읽고 쓰는 작업을 수행해야 할 수 있으며, 자주 읽고 쓰면 성능 문제가 발생할 수 있습니다. 이러한 문제를 해결하기 위해 Java에서는 IO 작업의 효율성을 높이기 위해 버퍼링된 스트림(Buffered Stream)을 제공합니다. 버퍼링된 스트림은 내부 캐시 영역을 통해 기본 리소스에 대한 액세스 횟수를 줄여 데이터 읽기 및 쓰기 효율성을 향상시킬 수 있습니다.

    2.3 Java IO 사용

    2.3.1 파일 읽기 및 쓰기

    Java에서 파일 읽기 및 쓰기는 개발에서 가장 일반적인 작업 중 하나입니다. 다음은 파일의 내용을 읽고 출력하는 예입니다.

        try (FileInputStream fis = new FileInputStream("test.txt");
             InputStreamReader isr = new InputStreamReader(fis);
             BufferedReader br = new BufferedReader(isr)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    이 예에서는 FileInputStream, InputStreamReader, BufferedReader와 같은 클래스를 사용하여 파일 읽기를 완료합니다. 먼저 FileInputStream 클래스를 통해 입력 스트림 객체를 생성하고 읽을 파일의 이름을 지정한 다음 InputStreamReader를 사용하여 바이트 스트림을 문자 스트림으로 변환한 다음 BufferedReader를 사용하여 텍스트 내용을 한 줄씩 읽습니다.

    마찬가지로 Java에서 파일을 작성하는 것도 매우 간단합니다. 다음은 파일 작성의 예입니다.

    try (FileOutputStream fos = new FileOutputStream("test.txt");
         OutputStreamWriter osw = new OutputStreamWriter(fos);
         BufferedWriter bw = new BufferedWriter(osw)) {
        bw.write("Hello, world!");
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileOutputStream、OutputStreamWriter和BufferedWriter等类来完成文件的写入。首先,我们通过FileOutputStream类创建了一个输出流对象,并指定了要写入的文件名称;然后通过OutputStreamWriter将字节流转换为字符流,再通过BufferedWriter实现按行写入文本内容。

    3、Java NIO

    3.1 简介

    Java NIO(New IO)是Java SE 1.4引入的一个新的IO API,它提供了比传统IO更高效、更灵活的IO操作。与传统IO相比,Java NIO的优势在于它支持非阻塞IO和选择器(Selector)等特性,能够更好地支持高并发、高吞吐量的应用场景。本文将从NIO的基础知识讲起,逐步深入,介绍Java NIO的各个方面。

    3.2 核心概念

    3.2.1 选择器(Selector)

    选择器是Java NIO中的一个重要组件,它可以用于同时监控多个通道的读写事件,并在有事件发生时立即做出响应。选择器可以实现单线程监听多个通道的效果,从而提高系统吞吐量和运行效率。

    3.2.2 通道(Channel)

    通道是一个用于读写数据的对象,类似于Java IO中的流(Stream)。与流不同的是,通道可以进行非阻塞式的读写操作,并且可以同时进行读写操作。通道分为两种类型:FileChannel和SocketChannel,分别用于文件和网络

    通信。

    3.2.3 缓冲区(Buffer)

    在Java NIO中,所有数据都是通过缓冲区对象进行传输的。缓冲区是一段连续的内存块,可以保存需要读写的数据。缓冲区对象包含了一些状态变量,例如容量(capacity)、限制(limit)、位置(position)等,用于控制数据的读写。

    3.3 Java NIO的使用

    3.3.1 缓冲区操作

    Java NIO中的缓冲区操作主要包括数据读取和数据写入两种操作。下面是一个简单的缓冲区读取示例:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    try (FileChannel channel = new FileInputStream("test.txt").getChannel()) {
        int bytesRead = channel.read(buffer);
        while (bytesRead != -1) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                System.out.print((char) buffer.get());
            }
            buffer.clear();
            bytesRead = channel.read(buffer);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileChannel类和ByteBuffer类来完成文件的读取。首先,我们通过FileInputStream类创建了一个输入流对象,然后通过getChannel()方法获取到对应的通道对象;接着,我们创建了一个容量为1024字节的ByteBuffer对象,并调用read()方法从通道中读取数据,将读取到的数据保存在缓冲区中。读取完成后,我们通过flip()方法将缓冲区切换为读模式,并使用hasRemaining()和get()方法逐个读取数据;最后通过clear()方法清空缓冲区,准备进行下一轮读取。

    Java NIO中的缓冲区写操作也非常类似,下面是一个简单的缓冲区写入示例:

    ByteBuffer buffer = ByteBuffer.wrap("Hello, world!".getBytes());
    try (FileChannel channel = new FileOutputStream("test.txt").getChannel()) {
        channel.write(buffer);
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileChannel类和ByteBuffer类来完成文件的写入。首先,我们通过ByteBuffer.wrap()方法将字符串转换为ByteBuffer对象;然后,我们通过FileOutputStream类创建了一个输出流对象,再通过getChannel()方法获取到对应的通道对象;接着,我们调用write()方法将缓冲区中的数据写入通道中,完成文件写入操作。

    3.3.2 通道操作

    Java NIO中的通道(Channel)是用于进行数据传输的对象。通道可以连接到源或目标节点,用于读取和写入数据。与传统的Java IO不同,NIO中的通道可以实现非阻塞式地读写数据,从而提高了应用程序的性能和并发处理能力。

    要使用通道进行读写操作,首先需要打开通道。Java NIO中有多种类型的通道,每种通道都提供了自己的打开方式。例如,要打开一个文件通道,可以通过FileInputStream或FileOutputStream对象获取对应的FileChannel对象,如下所示:

        FileChannel channel = new FileInputStream("file.txt").getChannel();

    读取数据 一旦打开了通道,就可以开始读取数据。在NIO中,数据通过缓冲区进行传输。要读取数据,需要将数据存储在缓冲区中,然后从缓冲区中读取数据。以下是一个简单的读取操作示例:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    // 从通道中读取数据
    int bytesRead = channel.read(buffer);
    while (bytesRead != -1) {
        // 切换为读模式
        buffer.flip();
        // 读取缓冲区中的数据
        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get());
        }
        // 清空缓冲区
        buffer.clear();
        bytesRead = channel.read(buffer);
    }

    在这个示例中,我们首先创建了一个容量为1024字节的ByteBuffer对象,并使用channel.read()方法从文件通道中读取数据。读取到数据后,我们将ByteBuffer切换为读模式,再使用hasRemaining()和get()方法逐个读取缓冲区中的数据。

    写入数据 要写入数据,也需要将数据存储在缓冲区中,然后将缓冲区中的数据写入到通道中。以下是一个简单的写入操作示例:

    ByteBuffer buffer = ByteBuffer.wrap("Hello, world!".getBytes());
    // 将数据写入通道
    channel.write(buffer);

    在这个示例中,我们首先使用ByteBuffer.wrap()方法将字符串转换为ByteBuffer对象,在通过channel.write()方法将ByteBuffer中的数据写入到通道中。

    4、Java AIO

    Java AIO(Asynchronous IO)是一种基于事件和回调的IO模型,相比Java BIO(Blocking IO)和Java NIO(Non-blocking IO),它具有更高的并发性、更高的吞吐量和更高的可靠性。本文将介绍Java AIO的原理、特点和应用。

    4.1 Java AIO의 원리

    Java AIO는 비동기 IO를 사용하여 데이터를 읽고 씁니다. Java NIO와 달리 데이터 준비 여부를 확인하기 위해 폴링할 필요가 없으며 운영 체제에 의해 완료됩니다. 데이터가 준비되면 운영 체제는 애플리케이션에 알리고 콜백 함수에서 처리합니다.

    AIO는 AsynchronousChannel, CompletionHandler 및
    AsynchronousServerSocketChannel이라는 세 가지 핵심 구성 요소를 사용합니다. 그 중 AsynchronousChannel은 데이터 읽기/쓰기를 위한 채널이고, CompletionHandler는 I/O 작업 완료 시 콜백 메서드이며, AsynchronousServerSocketChannel은 클라이언트의 연결 요청을 모니터링하는 데 사용되는 비동기 서버측 소켓 채널입니다.

    데이터가 준비되면 운영 체제는 애플리케이션에 알리고 I/O 작업이 완료되면 콜백 함수의 콜백 메서드를 실행합니다. 이렇게 하면 I/O 작업이 완료될 때까지 스레드가 차단되는 상황이 방지되므로 프로그램의 효율성과 동시 처리 기능이 향상됩니다.

    4.2 Java AIO의 특징

    • 높은 동시성: Java AIO는 데이터 읽기 및 쓰기 작업에 비동기 IO를 사용하므로 높은 동시성 처리 기능을 달성할 수 있습니다.

    • 높은 처리량: Java AIO는 비동기식 읽기 및 쓰기 작업을 지원하고 동시에 여러 요청을 처리할 수 있으므로 데이터 읽기 및 쓰기의 효율성과 처리량이 향상됩니다.

    • 높은 안정성: Java AIO는 데이터 읽기 및 쓰기 작업에 비동기 IO를 사용하므로 I/O 작업이 완료될 때까지 기다리는 스레드 차단을 방지하여 프로그램의 안정성을 향상시킬 수 있습니다.

    • 간단하고 사용하기 쉬움: Java AIO는 간단하고 사용하기 쉬운 API를 제공하며 복잡한 코드를 작성하지 않고도 비동기 IO 작업을 구현할 수 있습니다.

    4.3 Java AIO 애플리케이션

    Java AIO는 많은 동시 연결이 필요한 시나리오에 적합하지만 메시지 기반 애플리케이션, RPC(원격 프로시저 호출) 등과 같이 각 연결에 데이터 상호 작용이 거의 없습니다. 이러한 애플리케이션 시나리오에서 AIO는 프로그램의 성능과 동시 처리 기능을 크게 향상시켜 높은 처리량과 낮은 대기 시간에 대한 사용자 요구 사항을 충족할 수 있습니다.

    또한 Java AIO를 사용하여 채팅방 서버, 온라인 게임 서버 등 고성능 네트워크 서버를 개발할 수도 있습니다. AIO는 입력 및 출력 스트림의 비동기식 읽기를 지원하므로 동시에 여러 클라이언트 요청을 처리할 수 있어 서버의 동시 처리 기능이 효과적으로 향상됩니다.

    요약

    Java AIO는 고성능, 높은 동시성 IO 모델로서 많은 장점을 갖고 있지만 몇 가지 단점도 있습니다. 예를 들어 부하가 작은 연결의 경우 AIO 오버헤드로 인해 성능이 저하될 수 있습니다. 따라서 실제 적용에서는 실제 요구 사항에 따라 다양한 요소를 평가하고 선택해야 합니다.

    5. 관련 면접 질문

    1. Java IO와 NIO란?

    Java IO(입력/출력)는 데이터 전송을 위해 바이트 스트림과 문자 스트림을 사용하는 Java의 전통적인 입력 및 출력 작업입니다.
    Java NIO(New Input/Output)는 Java 1.4에 도입된 새로운 입력 및 출력 API로, 데이터를 보다 효율적으로 처리합니다.

    2. 차단 및 비차단 IO란 무엇인가요?

    Blocking IO(Blocking IO)는 IO 작업 중 IO가 완료될 때까지 대기하며, 이 기간 동안에는 다른 작업을 수행할 수 없습니다.
    Non-blocking IO(Non-blocking IO)는 IO 작업을 수행할 때 영원히 기다리지 않고 즉시 결과를 반환합니다. IO가 완전히 완료되지 않은 경우 다른 작업을 계속할 수 있습니다.

    3. 완충지대란? 어떤 종류의 버퍼가 있나요?

    버퍼는 데이터를 저장하는 데 사용되는 배열입니다. IO 작업을 수행할 때 데이터를 읽고 쓰는 데 사용되는 버퍼입니다.
    Java 버퍼는 바이트 버퍼(ByteBuffer, CharBuffer, ShortBuffer 등)와 직접 버퍼(DirectByteBuffer, DirectCharBuffer, DirectShortBuffer 등)로 구분됩니다.

    4. 채널이란 무엇인가요?

    채널은 NIO에서 데이터 전송에 사용되는 개체입니다. 데이터를 읽고 쓰기 위해 소스 또는 대상 노드에 연결할 수 있습니다.

    5. 선택자란 무엇인가요?

    선택기는 NIO에 등록된 채널을 폴링하여 이벤트(예: 읽기 가능, 쓰기 가능 등)가 있는지 확인할 수 있으므로 IO 차단 시 IO가 완료될 때까지 기다릴 필요가 없습니다. 문제.

    6. Java IO와 NIO의 차이점은 무엇인가요?

    Java IO는 스트림을 기반으로 데이터를 전송하는 반면, NIO는 버퍼와 채널을 기반으로 데이터를 전송합니다.
    Java IO는 차단 중이지만 NIO는 차단 또는 비차단 모드일 수 있습니다.
    Java IO는 더 많은 스레드를 사용하며 각 IO 작업에는 스레드 생성이 필요한 반면 NIO는 단일 스레드를 사용하여 여러 IO 작업을 처리할 수 있습니다.

    7. 파일채널이란 무엇인가요?

    파일 채널은 NIO에서 파일을 읽고 쓰는 데 사용되는 채널입니다. 이는 임의 액세스 및 메모리 매핑 파일과 같은 고급 기능을 지원합니다.

    8. Java IO와 NIO 중 어느 것이 더 빠릅니까?

    작은 데이터의 양이 많은 경우에는 버퍼를 통해 모든 데이터를 한번에 읽을 수 있기 때문에 Java IO가 더 빠를 수 있습니다.
    대규모 데이터 블록의 경우 NIO는 제로 복사 기술을 사용하여 디스크에서 메모리로 직접 데이터를 읽어 데이터 복사 오버헤드를 줄일 수 있으므로 더 빠를 수 있습니다.

    위 내용은 Java 입출력 IO, NIO, AIO 비교 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제