내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
기본 검토를 위해 ava 수준의 NIO에 대한 기본 지식을 설명합니다.
Java에서 NIO(Non-blocking I/O 또는 New I/O)는 Java SE 1.4 및 후속 버전에 도입된 새로운 입출력 작업 API 세트입니다.
기존 IO 모델과 비교하여 더 높은 효율성과 더 나은 동시 처리 기능을 제공합니다. NIO의 핵심 기능은 단일 스레드가 여러 I/O 채널을 관리할 수 있도록 하는 비차단 기능으로, 이를 통해 높은 동시성 시나리오에서 애플리케이션 성능을 크게 향상시킵니다.
Java NIO의 사용 시나리오는 많은 수의 동시 연결을 처리해야 하는 상황에 특히 적합합니다. 예를 들어 네트워크 서버에서는 각 연결에 대해 독립적인 스레드를 할당할 필요 없이 하나의 스레드가 수천 개의 클라이언트 연결을 관리할 수 있습니다. . 시스템 자원 소모를 대폭 줄이고 처리 능력을 향상시킬 수 있습니다.
채널은 Java NIO의 데이터 흐름 매체이며 양방향이며 데이터를 읽거나 쓰는 데 사용할 수 있습니다. 채널의 가장 큰 장점은 비차단형이라는 것입니다. 즉, 하나의 스레드가 여러 채널을 관리할 수 있다는 것입니다. 채널에서 이벤트가 발생하지 않으면 스레드가 차단되지 않고 대신 다른 작업을 처리할 수 있습니다. 주요 채널 유형은 다음과 같습니다.
FileChannel
: 파일 읽기 및 쓰기 작업에 사용됩니다. 버퍼에서 파일로 데이터를 쓰거나 파일에서 버퍼로 데이터를 읽는 데 사용할 수 있습니다.SocketChannel
: 네트워크 통신에서 TCP 연결에 사용되며, 데이터를 읽고 쓰는 데 사용할 수 있습니다.ServerSocketChannel
: 기존 ServerSocket과 유사하게 새로운 SocketChannel 연결을 허용하는 데 사용됩니다.DatagramChannel
: 데이터그램을 보내고 받을 수 있는 UDP 통신에 사용됩니다.버퍼(Buffer)는 NIO에 데이터를 저장하는 데 사용되는 객체로, 데이터를 쓰고 읽을 수 있는 바이트 배열입니다. 버퍼에는 특정 용량이 있으며 위치와 제한이라는 두 가지 중요한 속성이 있습니다.
버퍼의 주요 유형은 다음과 같습니다.ByteBuffer
、CharBuffer
、ShortBuffer
、IntBuffer
、LongBuffer
、FloatBuffer
그리고DoubleBuffer
, 각 유형은 기본 데이터 유형에 해당합니다.
선택기는 단일 스레드가 이벤트 읽기, 쓰기, 연결 및 수신과 같은 여러 채널의 이벤트를 모니터링할 수 있도록 하는 NIO의 멀티플렉서입니다. 선택기는 채널 중 하나가 I/O 작업 준비가 되면 애플리케이션에 알립니다. 선택기를 사용하면 각 연결에 대해 스레드를 생성할 필요가 없기 때문에 네트워크 애플리케이션의 동시성 처리 기능이 크게 향상됩니다.
선택기의 주요 방법은 다음과 같습니다.
select()
: 하나 이상의 채널이 I/O 작업 준비가 될 때까지 차단됩니다.selectedKeys()
: 준비된 모든 채널의 SelectionKey 개체가 포함된 세트를 반환합니다.wakeup()
: 인터럽트가 차단되었습니다.select()
옮기다.SelectionKey
이는 선택기와 채널 간의 연결로, 채널, 선택기, 관심 있는 이벤트 컬렉션 및 준비된 이벤트 컬렉션을 포함하여 선택기의 채널 등록 상태를 나타냅니다.
이는 가장 전통적인 I/O 모델입니다. Java에서 기존 Socket 및 ServerSocket API는 차단 I/O를 기반으로 합니다. 이 모드에서는 스레드가 읽기 또는 쓰기 작업을 시작하면 I/O 작업이 완료될 때까지 스레드가 차단됩니다. 읽기 작업을 위해 읽을 데이터가 없거나 쓰기 작업을 즉시 완료할 수 없는 경우 스레드는 작업이 완료될 때까지 기다립니다.
특징:
비차단 I/O는 스레드가 차단되지 않고 읽기 및 쓰기 작업을 시작할 수 있도록 하는 Java NIO(New I/O) 프레임워크의 일부입니다. 읽기 작업을 위해 읽을 데이터가 없거나 쓰기 작업을 즉시 완료할 수 없는 경우 스레드는 일시 중지되지 않고 계속해서 다른 작업을 수행할 수 있습니다.
특징:
멀티플렉싱은 하나의 스레드를 통해 동시에 여러 파일 설명자를 모니터링하고 준비가 된 설명자에서만 작동합니다(일반적으로 데이터를 읽을 수 있거나 쓰기 버퍼에 쓸 수 있음을 의미). 선택기는 Java에서 멀티플렉싱을 구현하는 데 사용됩니다.
특징:
알아채다:
실제 애플리케이션에서는 비차단 I/O가 멀티플렉싱과 함께 사용되는 경우가 많습니다. 예를 들어, 서버는 Selector를 사용하여 여러 SocketChannel을 모니터링할 수 있습니다. SocketChannel에 읽거나 쓸 수 있는 데이터가 있는 경우 Selector는 서버에 알리고 서버는 이 특정 SocketChannel을 비차단 방식으로 처리합니다.
Java에서 Stream과 Channel은 각각 Java의 표준 IO 라이브러리와 NIO 라이브러리에 속합니다. 두 개념을 자세히 비교하면 다음과 같습니다.
Stream은 데이터를 순차적으로 읽고 쓰는 방법을 제공하는 Java의 표준 IO(블로킹 IO) 모델의 일부입니다. 스트림은 데이터를 읽고 쓰는 데 사용되는 입력스트림(InputStream)과 출력스트림(OutputStream)의 두 가지 유형으로 구분됩니다.이러한 스트림은 바이트 스트림일 수 있습니다(예:InputStream
, OutputStream
) 또는 문자 스트림(예:Reader
, Writer
)。
특징:
close()
리소스를 해제하는 방법.Java 7부터 try-with-resources 문은 자동으로 구현을 닫을 수 있습니다.AutoCloseable
Stream을 포함한 인터페이스 리소스. 채널은 Stream보다 더 높은 수준의 추상화를 제공하여 보다 효율적인 데이터 처리를 가능하게 하는 Java NIO(New IO) 모델의 일부입니다. 채널은 양방향일 수 있습니다. 즉, 데이터를 읽고 쓰는 데 사용할 수 있습니다.주요 채널 유형은 다음과 같습니다.FileChannel
、SocketChannel
、ServerSocketChannel
그리고DatagramChannel
。
특징:
요약하다
Java에서 I/O 작업 모델은 동기/비동기 및 차단/비차단이라는 두 가지 차원을 기준으로 분류할 수 있습니다.
정의 : 동기 차단 I/O는 가장 전통적인 I/O 모델입니다. 스레드가 I/O 작업(예: 읽기 또는 쓰기)을 호출하면 작업이 완료될 때까지 스레드가 차단됩니다. 이는 작업이 완료될 때까지 스레드가 다른 작업을 수행할 수 없음을 의미합니다.
특징:
InputStream
、OutputStream
、Socket
그리고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();
}
}
}
정의 : 동기식 비차단 I/O에서는 I/O 작업을 호출한 후에도 스레드가 차단되지 않습니다. 작업을 즉시 완료할 수 없는 경우 메서드는 즉시 반환되며 일반적으로 특수 값(예: -1 또는 0)을 반환하거나 작업이 완료되지 않았음을 나타내는 예외를 발생시킵니다.
특징:
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();
}
}
}
정의: 동기식 다중화 I/O 모델 사용Selector
(선택기) 여러 모니터링Channel
이벤트.스레드가 호출될 때Selector.select()
, 적어도 하나가 있을 때까지 차단됩니다.Channel
이벤트(읽기 가능, 쓰기 가능, 연결 요청 등)가 발생합니다.
특징:
Channel
, 동시성을 향상시킵니다.Selector
그리고SelectionKey
많은 수의 동시 연결을 효율적으로 처리할 수 있는 메커니즘입니다.예:
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();
}
}
}
}
}
정의 : 비동기 비차단 I/O 모델에서 스레드는 작업이 완료될 때까지 기다리지 않고 I/O 작업을 시작한 후 즉시 반환됩니다. 작업이 완료되면 콜백 함수나 이벤트 알림을 통해 스레드에 비동기적으로 알림이 전달됩니다.
특징:
AsynchronousChannel
인터페이스 및 해당 하위 클래스 구현(예:AsynchronousFileChannel
그리고AsynchronousSocketChannel
。예:
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();
}
}
참고: 비동기식 모델에는 기본 운영 체제(커널)의 지원이 필요합니다.
정의 : 이론적으로 이 모델은 존재하지 않습니다. "비동기"는 작업이 백그라운드에서 수행되고 스레드가 차단되지 않음을 의미하기 때문입니다. 따라서 비동기식 차단 I/O는 모순되는 개념이며 실제로는 나타나지 않습니다.
적절한 I/O 모델을 선택하는 것은 성능 및 리소스 관리에 매우 중요합니다. 동시성이 높은 시나리오에서는 동기식 비차단 I/O 또는 동기식 다중화 I/O 모델이 일반적인 선택입니다. 최고의 성능과 응답 속도가 필요한 시나리오에서는 비동기식 비차단 I/O 모델이 첫 번째 선택입니다.
제로 카피 개념
제로카피 기술은 한 곳에서 다른 곳으로 데이터를 전송하는 과정에서 사용자 공간과 커널 공간 사이에서 데이터를 복사할 필요가 없거나 최소한 복사 횟수를 줄여 데이터의 효율성을 높이는 것을 의미한다. 체계. 기존 I/O 작업에서는 네트워크나 디스크에서 데이터를 읽을 때 먼저 커널 공간의 버퍼에 복사된 다음 커널 공간에서 사용자 공간의 버퍼로 복사됩니다. 반면, 제로 복사에서는 데이터를 커널 공간에서 직접 처리하거나 커널 공간에서 네트워크 장치로 직접 전송할 수 있으므로 CPU 복사 작업이 줄어들고 시스템 오버헤드가 줄어들며 데이터 전송 효율성이 향상됩니다.
제로 카피의 소스
제로 복사 개념은 기존 I/O 작업에서 데이터 복사로 인해 발생하는 성능 병목 현상을 해결하기 위해 운영 체제 설계에서 처음 등장했습니다. 초기 컴퓨터 시스템에서는 모든 I/O 작업에 사용자 공간과 커널 공간 사이에 여러 개의 데이터 복사본이 필요했습니다. 이는 고속 네트워크와 대용량 디스크가 보편화되면서 점차 성능 병목 현상이 되었습니다.
주요 기술 포인트
Java로 구현:
Java는 NIO(New I/O) 프레임워크를 통해 제로 복사 기술을 지원합니다. NIO 도입FileChannel
그리고SocketChannel
및 보다 효율적인 I/O 작업을 제공하는 기타 클래스입니다. 구체적으로,FileChannel.transferTo()
그리고FileChannel.transferFrom()
메서드는 데이터를 버퍼에 로드하지 않고 파일 채널에서 소켓 채널로 직접 또는 그 반대로 데이터를 전송할 수 있으므로 복사가 필요하지 않습니다.
예를 들어, 대용량 파일의 내용을 네트워크로 보내야 한다고 가정해 보겠습니다. 전통적인 접근 방식은 먼저 파일 내용을 버퍼로 읽은 다음 버퍼 내용을 네트워크에 쓰는 것입니다. 여기에는 두 가지 복사 작업이 포함됩니다. 하나는 디스크에서 버퍼로, 다른 하나는 버퍼에서 네트워크로.사용하는 동안transferTo()
이 방법을 사용하면 중간 버퍼 없이 데이터를 디스크에서 네트워크로 직접 전송할 수 있으므로 복사본 수가 줄어들고 제로 복사본이 달성됩니다.
ByteBuffer를 사용한 예:
ByteBuffer
및 기타Buffer
수업(예:CharBuffer
,ShortBuffer
등)은 사용자 공간과 커널 공간 간의 복사를 직접적으로 포함하지 않고 채우거나 비울 수 있는 버퍼를 제공합니다.ByteBuffer
제로 복사 기술에서 직접 또는 간접적으로 사용될 수 있습니다.
ByteBuffer.allocateDirect(size)
만들어진ByteBuffer
인스턴스는 Java 힙을 우회하여 실제 메모리에 직접 매핑됩니다.이러한 버퍼를 다음과 비교할 때FileChannel
또는SocketChannel
함께 사용하면 Java 힙을 통한 추가 복사본 없이 물리적 메모리와 하드웨어 장치 간에 데이터를 직접 전송할 수 있습니다. 이를 통해 일부 플랫폼에서는 진정한 제로 복사가 가능해집니다.FileChannel
~의transferTo()
그리고transferFrom()
: 이 방법을 사용하면 데이터를 직접 저장할 수 있습니다.FileChannel
그리고SocketChannel
사이에 전송ByteBuffer
중개자로서. 이는 사용자 공간과 커널 공간 사이에 복사할 필요 없이 데이터를 디스크에서 네트워크로 또는 그 반대로 직접 전송할 수 있음을 의미합니다.ByteBuffer
~의wrap()
방법:wrap()
메서드를 사용하면 기존 바이트 배열이나 다른 버퍼를ByteBuffer
, 따라서 데이터를 새 버퍼에 복사할 필요가 없습니다. 이는 불필요한 데이터 복사를 방지하는 데 유용합니다.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();
}
}
}
알아채다:
실제로 완전한 제로 복사본은 없다는 점에 유의해야 합니다. 여기서 언급한 제로 복사본은 사용자 수준 복사본이 없는 애플리케이션 자체에만 해당됩니다. 그러나 사용자 수준에서도 복사 작업을 전혀 하지 않는 것은 불가능하며, 복사를 최대한 줄이는 것이 가능합니다. 따라서 제로 복사라는 용어는 실제로 데이터 복사본 수를 줄이는 기술을 의미하는 것으로 이해할 수 있습니다. 실제 복사 작업이 없다는 의미는 아닙니다.