기술나눔

Java 네트워크 모델의 완전한 읽기 능력

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

개요

기본 검토를 위해 ava 수준의 NIO에 대한 기본 지식을 설명합니다.

1. NIO 개요

Java에서 NIO(Non-blocking I/O 또는 New I/O)는 Java SE 1.4 및 후속 버전에 도입된 새로운 입출력 작업 API 세트입니다.

​ 기존 IO 모델과 비교하여 더 높은 효율성과 더 나은 동시 처리 기능을 제공합니다. NIO의 핵심 기능은 단일 스레드가 여러 I/O 채널을 관리할 수 있도록 하는 비차단 기능으로, 이를 통해 높은 동시성 시나리오에서 애플리케이션 성능을 크게 향상시킵니다.

Java NIO의 사용 시나리오는 많은 수의 동시 연결을 처리해야 하는 상황에 특히 적합합니다. 예를 들어 네트워크 서버에서는 각 연결에 대해 독립적인 스레드를 할당할 필요 없이 하나의 스레드가 수천 개의 클라이언트 연결을 관리할 수 있습니다. . 시스템 자원 소모를 대폭 줄이고 처리 능력을 향상시킬 수 있습니다.

2. Java에서 NIO의 세 가지 주요 구성 요소

1. 채널

채널은 Java NIO의 데이터 흐름 매체이며 양방향이며 데이터를 읽거나 쓰는 데 사용할 수 있습니다. 채널의 가장 큰 장점은 비차단형이라는 것입니다. 즉, 하나의 스레드가 여러 채널을 관리할 수 있다는 것입니다. 채널에서 이벤트가 발생하지 않으면 스레드가 차단되지 않고 대신 다른 작업을 처리할 수 있습니다. 주요 채널 유형은 다음과 같습니다.

  • FileChannel: 파일 읽기 및 쓰기 작업에 사용됩니다. 버퍼에서 파일로 데이터를 쓰거나 파일에서 버퍼로 데이터를 읽는 데 사용할 수 있습니다.
  • SocketChannel: 네트워크 통신에서 TCP 연결에 사용되며, 데이터를 읽고 쓰는 데 사용할 수 있습니다.
  • ServerSocketChannel: 기존 ServerSocket과 유사하게 새로운 SocketChannel 연결을 허용하는 데 사용됩니다.
  • DatagramChannel: 데이터그램을 보내고 받을 수 있는 UDP 통신에 사용됩니다.

2. 버퍼

​버퍼(Buffer)는 NIO에 데이터를 저장하는 데 사용되는 객체로, 데이터를 쓰고 읽을 수 있는 바이트 배열입니다. 버퍼에는 특정 용량이 있으며 위치와 제한이라는 두 가지 중요한 속성이 있습니다.

  • 용량: 버퍼가 저장할 수 있는 최대 요소 수입니다.
  • 위치: 현재 연산 중인 요소의 인덱스로, 데이터를 읽거나 쓸 때 변경됩니다.
  • 한계: 읽기 모드에서는 위치가 쓰기 모드에서 도달할 수 있는 최대값이며 위치는 이 값을 초과할 수 없습니다.

버퍼의 주요 유형은 다음과 같습니다.ByteBufferCharBufferShortBufferIntBufferLongBufferFloatBuffer그리고DoubleBuffer, 각 유형은 기본 데이터 유형에 해당합니다.

3. 선택자

선택기는 단일 스레드가 이벤트 읽기, 쓰기, 연결 및 수신과 같은 여러 채널의 이벤트를 모니터링할 수 있도록 하는 NIO의 멀티플렉서입니다. 선택기는 채널 중 하나가 I/O 작업 준비가 되면 애플리케이션에 알립니다. 선택기를 사용하면 각 연결에 대해 스레드를 생성할 필요가 없기 때문에 네트워크 애플리케이션의 동시성 처리 기능이 크게 향상됩니다.

선택기의 주요 방법은 다음과 같습니다.

  • select(): 하나 이상의 채널이 I/O 작업 준비가 될 때까지 차단됩니다.
  • selectedKeys(): 준비된 모든 채널의 SelectionKey 개체가 포함된 세트를 반환합니다.
  • wakeup(): 인터럽트가 차단되었습니다.select()옮기다.

SelectionKey이는 선택기와 채널 간의 연결로, 채널, 선택기, 관심 있는 이벤트 컬렉션 및 준비된 이벤트 컬렉션을 포함하여 선택기의 채널 등록 상태를 나타냅니다.

3. 네트워크 프로그래밍

1. I/O 차단

​ 이는 가장 전통적인 I/O 모델입니다. Java에서 기존 Socket 및 ServerSocket API는 차단 I/O를 기반으로 합니다. 이 모드에서는 스레드가 읽기 또는 쓰기 작업을 시작하면 I/O 작업이 완료될 때까지 스레드가 차단됩니다. 읽기 작업을 위해 읽을 데이터가 없거나 쓰기 작업을 즉시 완료할 수 없는 경우 스레드는 작업이 완료될 때까지 기다립니다.

특징:

  • 간단한 프로그래밍 모델: 이해하고 구현하기 쉽습니다.
  • 자원점유: 각 연결에는 독립적인 스레드가 필요하므로 스레드 수가 제한되고 리소스 소비가 높아집니다.
  • 성능 제한: 동시성이 높은 시나리오에서 스레드 전환 및 컨텍스트 전환은 비용이 많이 들고 쉽게 병목 현상이 발생할 수 있습니다.

2. 논블로킹 I/O

​ 비차단 I/O는 스레드가 차단되지 않고 읽기 및 쓰기 작업을 시작할 수 있도록 하는 Java NIO(New I/O) 프레임워크의 일부입니다. 읽기 작업을 위해 읽을 데이터가 없거나 쓰기 작업을 즉시 완료할 수 없는 경우 스레드는 일시 중지되지 않고 계속해서 다른 작업을 수행할 수 있습니다.

특징:

  • 유연성: 스레드는 I/O 작업을 기다리면서 차단되지 않으므로 더 많은 연결을 처리할 수 있습니다.
  • 복잡성 증가: 프로그래머는 작업이 완료되었는지 명시적으로 확인해야 하므로 프로그래밍의 난이도가 높아집니다.
  • 성능 개선: 동시성이 높은 시나리오에서는 스레드 전환으로 인한 오버헤드를 크게 줄일 수 있습니다.

3. 다중화

​ 멀티플렉싱은 하나의 스레드를 통해 동시에 여러 파일 설명자를 모니터링하고 준비가 된 설명자에서만 작동합니다(일반적으로 데이터를 읽을 수 있거나 쓰기 버퍼에 쓸 수 있음을 의미). 선택기는 Java에서 멀티플렉싱을 구현하는 데 사용됩니다.

특징:

  • 높은 동시성: 하나의 스레드가 수천 개의 연결을 처리할 수 있어 서버 처리량이 크게 향상됩니다.
  • 효율적인: I/O 작업이 준비된 경우에만 불필요한 스레드 전환을 방지하기 위해 스레드가 깨어납니다.
  • 자원 절약: I/O 차단에 비해 다중화 모델의 서버는 시스템 자원을 보다 효율적으로 활용할 수 있습니다.

알아채다:

실제 애플리케이션에서는 비차단 I/O가 멀티플렉싱과 함께 사용되는 경우가 많습니다. 예를 들어, 서버는 Selector를 사용하여 여러 SocketChannel을 모니터링할 수 있습니다. SocketChannel에 읽거나 쓸 수 있는 데이터가 있는 경우 Selector는 서버에 알리고 서버는 이 특정 SocketChannel을 비차단 방식으로 처리합니다.

4.NIO 대 BIO

4.1 스트림 대 채널

Java에서 Stream과 Channel은 각각 Java의 표준 IO 라이브러리와 NIO 라이브러리에 속합니다. 두 개념을 자세히 비교하면 다음과 같습니다.

개울

Stream은 데이터를 순차적으로 읽고 쓰는 방법을 제공하는 Java의 표준 IO(블로킹 IO) 모델의 일부입니다. 스트림은 데이터를 읽고 쓰는 데 사용되는 입력스트림(InputStream)과 출력스트림(OutputStream)의 두 가지 유형으로 구분됩니다.이러한 스트림은 바이트 스트림일 수 있습니다(예:InputStream, OutputStream) 또는 문자 스트림(예:Reader, Writer)。

특징:

  • 방해가 되는: 기본적으로 스트림 작업은 차단됩니다. 즉, 읽기 작업을 위해 읽을 데이터가 없거나 쓰기 작업을 즉시 완료할 수 없는 경우 작업이 완료될 때까지 호출 스레드가 차단됩니다.
  • 단방향성: 각 스트림에는 읽기 전용 또는 쓰기 전용 방향이 있습니다.
  • 자동 종료: Stream을 사용한 후에는 일반적으로 Stream을 호출해야 합니다.close() 리소스를 해제하는 방법.Java 7부터 try-with-resources 문은 자동으로 구현을 닫을 수 있습니다.AutoCloseableStream을 포함한 인터페이스 리소스.

채널

채널은 Stream보다 더 높은 수준의 추상화를 제공하여 보다 효율적인 데이터 처리를 가능하게 하는 Java NIO(New IO) 모델의 일부입니다. 채널은 양방향일 수 있습니다. 즉, 데이터를 읽고 쓰는 데 사용할 수 있습니다.주요 채널 유형은 다음과 같습니다.FileChannelSocketChannelServerSocketChannel그리고DatagramChannel

특징:

  • 비차단 :채널은 차단 또는 비차단 모드로 구성될 수 있습니다. 비차단 모드에서는 읽기 작업에 읽을 데이터가 없거나 쓰기 작업을 즉시 완료할 수 없는 경우 스레드를 차단하는 대신 작업이 즉시 반환됩니다.
  • 버퍼 작업:채널 연산은 항상 버퍼(Buffer)를 통해 수행됩니다. 데이터는 채널에서 버퍼로 읽혀지거나 버퍼에서 채널로 쓰여집니다.
  • 멀티플렉싱: 채널을 Selector와 함께 사용하여 멀티플렉싱을 달성하면 하나의 스레드가 여러 채널의 I/O 작업을 모니터링하고 동시 처리 기능을 향상시킬 수 있습니다.

요약하다

  • 적용 가능한 장면: 스트림은 더 작은 데이터 세트나 간단한 파일 작업을 처리하는 데 더 적합하고, 채널은 더 높은 성능과 더 나은 동시성 기능을 제공하므로 대용량 데이터, 특히 네트워크 통신 및 대용량 파일 작업을 처리하는 데 더 적합합니다.
  • 프로그래밍 복잡성: Stream의 API는 비교적 간단하고 사용하기 쉬운 반면, Channel 및 NIO의 API는 더 복잡하지만 더 강력한 기능과 더 높은 효율성을 제공합니다.
  • 자원 관리: 스트림이든 채널이든 리소스를 적절하게 관리해야 하며 리소스 누출을 방지하기 위해 더 이상 필요하지 않은 경우 닫혀 있는지 확인해야 합니다.

4.2.IO 모델

Java에서 I/O 작업 모델은 동기/비동기 및 차단/비차단이라는 두 가지 차원을 기준으로 분류할 수 있습니다.

4.2.1 동기식 차단 I/O

정의 : 동기 차단 I/O는 가장 전통적인 I/O 모델입니다. 스레드가 I/O 작업(예: 읽기 또는 쓰기)을 호출하면 작업이 완료될 때까지 스레드가 차단됩니다. 이는 작업이 완료될 때까지 스레드가 다른 작업을 수행할 수 없음을 의미합니다.

특징

  • 간단하고 사용하기 쉬우며 코드 논리가 명확합니다.
  • 각 I/O 작업에는 단독 스레드가 필요합니다. 이는 높은 동시성 시나리오에 적합하지 않으며 스레드 리소스가 고갈될 수 있습니다.
  • 일반적으로 사용되는InputStreamOutputStreamSocket그리고ServerSocket장면.

예:

전통을 사용하다InputStream그리고OutputStream파일을 읽고 쓰려면:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class SyncBlockingIOExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("input.txt");
             FileOutputStream fos = new FileOutputStream("output.txt")) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

4.2.2 동기식 비차단 I/O

정의 : 동기식 비차단 I/O에서는 I/O 작업을 호출한 후에도 스레드가 차단되지 않습니다. 작업을 즉시 완료할 수 없는 경우 메서드는 즉시 반환되며 일반적으로 특수 값(예: -1 또는 0)을 반환하거나 작업이 완료되지 않았음을 나타내는 예외를 발생시킵니다.

특징

  • 작업이 완료될 때까지 작업 상태를 폴링해야 합니다.
  • 스레드가 I/O를 기다리는 동안 다른 작업을 수행할 수 있으므로 스레드 활용도가 높아집니다.
  • 구현은 더 복잡하며 폴링 및 상태 확인을 처리해야 합니다.
  • Java NIO 기반Channels그리고Buffers, 전화로configureBlocking(false)채널을 비차단 모드로 설정하세요.

예:

NIO 사용FileChannel비차단 읽기 및 쓰기의 경우:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

public class SyncNonBlockingIOExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("input.txt");
             FileOutputStream fos = new FileOutputStream("output.txt");
             FileChannel inChannel = fis.getChannel();
             FileChannel outChannel = fos.getChannel()) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            inChannel.configureBlocking(false);
            while (inChannel.read(buffer) > 0) {
                buffer.flip();
                outChannel.write(buffer);
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

4.2.3 동기식 다중화 I/O

정의: 동기식 다중화 I/O 모델 사용Selector(선택기) 여러 모니터링Channel 이벤트.스레드가 호출될 때Selector.select(), 적어도 하나가 있을 때까지 차단됩니다.Channel이벤트(읽기 가능, 쓰기 가능, 연결 요청 등)가 발생합니다.

특징

  • 하나의 스레드가 여러 개를 관리할 수 있도록 허용Channel, 동시성을 향상시킵니다.
  • 통과하다Selector그리고SelectionKey많은 수의 동시 연결을 효율적으로 처리할 수 있는 메커니즘입니다.
  • 웹 서버 및 채팅 서버와 같은 네트워크 서버 시나리오에 적합합니다.
  • Java NIO 프레임워크를 기반으로 합니다.

예:

NIO 사용FileChannel비차단 읽기 및 쓰기의 경우:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;

public class SyncMultiplexingIOExample {
    public static void main(String[] args) throws IOException {
        try (Selector selector = Selector.open();
             ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
            serverSocketChannel.socket().bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            while (true) {
                if (selector.select() > 0) {
                    Set<SelectionKey> keys = selector.selectedKeys();
                    for (SelectionKey key : keys) {
                        if (key.isAcceptable()) {
                            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                            SocketChannel clientChannel = ssc.accept();
                            clientChannel.configureBlocking(false);
                            clientChannel.register(selector, SelectionKey.OP_READ);
                        }
                    }
                    keys.clear();
                }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

4.2.4 비동기 비차단 I/O

정의 : 비동기 비차단 I/O 모델에서 스레드는 작업이 완료될 때까지 기다리지 않고 I/O 작업을 시작한 후 즉시 반환됩니다. 작업이 완료되면 콜백 함수나 이벤트 알림을 통해 스레드에 비동기적으로 알림이 전달됩니다.

특징

  • 가장 효율적인 I/O 모델인 스레드는 전혀 차단되지 않으며 즉시 다른 작업을 수행할 수 있습니다.
  • 통과하다AsynchronousChannel인터페이스 및 해당 하위 클래스 구현(예:AsynchronousFileChannel그리고AsynchronousSocketChannel
  • 빅 데이터 처리 및 고부하 네트워크 서버와 같은 높은 동시성 및 고성능 시나리오에 적합합니다.
  • Java 7에서는 비동기 비차단 I/O 모델을 도입했습니다.

예:

NIO 사용AsynchronousFileChannel비동기식 파일 읽기 및 쓰기를 수행합니다.

import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;

public class AsyncNonBlockingIOExample {
    public static void main(String[] args) throws IOException, InterruptedException {
        AsynchronousFileChannel inChannel = AsynchronousFileChannel.open(Paths.get("input.txt"), StandardOpenOption.READ);
        AsynchronousFileChannel outChannel = AsynchronousFileChannel.open(Paths.get("output.txt"), StandardOpenOption.WRITE);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        CountDownLatch latch = new CountDownLatch(1);
        inChannel.read(buffer, 0, buffer, 0, (channel, result) -> {
            buffer.flip();
            outChannel.write(buffer, 0, buffer, 0, null);
            latch.countDown();
        });
        latch.await();
        inChannel.close();
        outChannel.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

참고: 비동기식 모델에는 기본 운영 체제(커널)의 지원이 필요합니다.

  • Windows 시스템은 IOCP를 통해 진정한 비동기 IO를 구현합니다.
  • Linux 시스템의 비동기 IO는 버전 2.6에서 도입되었지만 기본 구현은 여전히 ​​멀티플렉싱을 사용하여 비동기 IO를 시뮬레이션하므로 성능 이점이 없습니다.

4.2.5 비동기식 차단 I/O

정의 : 이론적으로 이 모델은 존재하지 않습니다. "비동기"는 작업이 백그라운드에서 수행되고 스레드가 차단되지 않음을 의미하기 때문입니다. 따라서 비동기식 차단 I/O는 모순되는 개념이며 실제로는 나타나지 않습니다.

4.2.6 요약

적절한 I/O 모델을 선택하는 것은 성능 및 리소스 관리에 매우 중요합니다. 동시성이 높은 시나리오에서는 동기식 비차단 I/O 또는 동기식 다중화 I/O 모델이 일반적인 선택입니다. 최고의 성능과 응답 속도가 필요한 시나리오에서는 비동기식 비차단 I/O 모델이 첫 번째 선택입니다.

4.3 제로 카피

제로 카피 개념

​ 제로카피 기술은 한 곳에서 다른 곳으로 데이터를 전송하는 과정에서 사용자 공간과 커널 공간 사이에서 데이터를 복사할 필요가 없거나 최소한 복사 횟수를 줄여 데이터의 효율성을 높이는 것을 의미한다. 체계. 기존 I/O 작업에서는 네트워크나 디스크에서 데이터를 읽을 때 먼저 커널 공간의 버퍼에 복사된 다음 커널 공간에서 사용자 공간의 버퍼로 복사됩니다. 반면, 제로 복사에서는 데이터를 커널 공간에서 직접 처리하거나 커널 공간에서 네트워크 장치로 직접 전송할 수 있으므로 CPU 복사 작업이 줄어들고 시스템 오버헤드가 줄어들며 데이터 전송 효율성이 향상됩니다.

제로 카피의 소스

제로 복사 개념은 기존 I/O 작업에서 데이터 복사로 인해 발생하는 성능 병목 현상을 해결하기 위해 운영 체제 설계에서 처음 등장했습니다. 초기 컴퓨터 시스템에서는 모든 I/O 작업에 사용자 공간과 커널 공간 사이에 여러 개의 데이터 복사본이 필요했습니다. 이는 고속 네트워크와 대용량 디스크가 보편화되면서 점차 성능 병목 현상이 되었습니다.

주요 기술 포인트

  • 직접 I/O: 애플리케이션이 파일 시스템의 캐싱 메커니즘을 건너뛰고 디스크 장치에 직접 액세스할 수 있도록 허용합니다.
  • 메모리 매핑(MMAP): 파일 데이터를 메모리처럼 액세스할 수 있도록 파일을 메모리에 매핑하여 복사를 줄입니다.
  • 보내기파일: 중간 복사본을 피하면서 한 파일 설명자에서 다른 파일 설명자로 직접 데이터를 전송할 수 있는 Linux 시스템 호출입니다.
  • DMA(Direct Memory Access): CPU 개입 없이 장치와 메모리 간에 직접 데이터를 전송할 수 있는 하드웨어 수준의 기술입니다.

Java로 구현:

Java는 NIO(New I/O) 프레임워크를 통해 제로 복사 기술을 지원합니다. NIO 도입FileChannel그리고SocketChannel 및 보다 효율적인 I/O 작업을 제공하는 기타 클래스입니다. 구체적으로,FileChannel.transferTo()그리고FileChannel.transferFrom()메서드는 데이터를 버퍼에 로드하지 않고 파일 채널에서 소켓 채널로 직접 또는 그 반대로 데이터를 전송할 수 있으므로 복사가 필요하지 않습니다.

예를 들어, 대용량 파일의 내용을 네트워크로 보내야 한다고 가정해 보겠습니다. 전통적인 접근 방식은 먼저 파일 내용을 버퍼로 읽은 다음 버퍼 내용을 네트워크에 쓰는 것입니다. 여기에는 두 가지 복사 작업이 포함됩니다. 하나는 디스크에서 버퍼로, 다른 하나는 버퍼에서 네트워크로.사용하는 동안transferTo()이 방법을 사용하면 중간 버퍼 없이 데이터를 디스크에서 네트워크로 직접 전송할 수 있으므로 복사본 수가 줄어들고 제로 복사본이 달성됩니다.

ByteBuffer를 사용한 예:

ByteBuffer및 기타Buffer수업(예:CharBufferShortBuffer등)은 사용자 공간과 커널 공간 간의 복사를 직접적으로 포함하지 않고 채우거나 비울 수 있는 버퍼를 제공합니다.ByteBuffer제로 복사 기술에서 직접 또는 간접적으로 사용될 수 있습니다.

  1. 다이렉트 버퍼ByteBuffer.allocateDirect(size)만들어진ByteBuffer 인스턴스는 Java 힙을 우회하여 실제 메모리에 직접 매핑됩니다.이러한 버퍼를 다음과 비교할 때FileChannel또는SocketChannel 함께 사용하면 Java 힙을 통한 추가 복사본 없이 물리적 메모리와 하드웨어 장치 간에 데이터를 직접 전송할 수 있습니다. 이를 통해 일부 플랫폼에서는 진정한 제로 복사가 가능해집니다.
  2. 사용FileChannel~의transferTo()그리고transferFrom(): 이 방법을 사용하면 데이터를 직접 저장할 수 있습니다.FileChannel그리고SocketChannel사이에 전송ByteBuffer 중개자로서. 이는 사용자 공간과 커널 공간 사이에 복사할 필요 없이 데이터를 디스크에서 네트워크로 또는 그 반대로 직접 전송할 수 있음을 의미합니다.
  3. 사용ByteBuffer~의wrap()방법wrap()메서드를 사용하면 기존 바이트 배열이나 다른 버퍼를ByteBuffer , 따라서 데이터를 새 버퍼에 복사할 필요가 없습니다. 이는 불필요한 데이터 복사를 방지하는 데 유용합니다.
  4. 사용ByteBuffer~의slice()방법slice() 메서드는 기본 데이터를 복사하지 않고 버퍼 보기를 만듭니다.이는 대규모ByteBuffer데이터를 복사하지 않고 여러 개의 작은 버퍼로 분할합니다.

ByteBuffer를 FileChannel과 결합합니다.

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class ZeroCopyExample {
    public static void main(String[] args) {
        Path path = Path.of("example.txt");
        try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
            long transferred = fileChannel.transferTo(0, fileChannel.size(), System.out);
            System.out.println("Transferred bytes: " + transferred);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

알아채다:

실제로 완전한 제로 복사본은 없다는 점에 유의해야 합니다. 여기서 언급한 제로 복사본은 사용자 수준 복사본이 없는 애플리케이션 자체에만 해당됩니다. 그러나 사용자 수준에서도 복사 작업을 전혀 하지 않는 것은 불가능하며, 복사를 최대한 줄이는 것이 가능합니다. 따라서 제로 복사라는 용어는 실제로 데이터 복사본 수를 줄이는 기술을 의미하는 것으로 이해할 수 있습니다. 실제 복사 작업이 없다는 의미는 아닙니다.