자바 NIO 와 IO

자바 NIO 와 IO 의 API 를 배 운 후에 한 가지 문제 가 곧 마음 에 들 었 습 니 다.
나 는 언제 IO 를 사용 해 야 합 니까? 언제 NIO 를 사용 해 야 합 니까?
본 논문 에서 저 는 자바 NIO 와 IO 의 차이, 그들의 사례, 그리고 이들 이 귀하 의 코드 디자인 에 어떻게 영향 을 미 치 는 지 명확 하 게 밝 힐 것 입 니 다.
자바 NIO 와 IO 의 주요 차이
다음 표 는 자바 NIO 와 IO 간 의 주요 차 이 를 정리 하고 표 의 각 부분의 차 이 를 더욱 상세 하 게 묘사 하 겠 습 니 다.
IO
NIO
흐름 을 향 하 다
버퍼 지향
막 힌 IO
비 차단 IO
 
선택 기
흐름 지향 및 버퍼 지향
자바 NIO 와 IO 사이 의 첫 번 째 가장 큰 차 이 는 IO 가 흐름 을 향 한 것 이 고 그 중에서 NIO 는 버퍼 를 향 한 것 이다.그럼, 자 는 무슨 뜻 입 니까?
자바 IO 가 흐름 을 향 해 흐 르 는 것 은 모든 바 이 트 를 읽 을 때 까지 스 트림 에서 하나 이상 의 바 이 트 를 읽 는 것 을 의미 합 니 다. 캐 시 되 어 있 지 않 습 니 다.또한 스 트림 의 데 이 터 를 앞 뒤로 이동 할 수 없습니다.흐름 에서 읽 은 데 이 터 를 앞 뒤로 이동 하려 면 버퍼 에 캐 시 해 야 합 니 다.
자바 NIO 의 버퍼 가이드 방법 은 약간 다르다.데 이 터 는 나중에 처리 할 버퍼 를 읽 습 니 다. 필요 할 때 버퍼 에서 앞 뒤로 이동 할 수 있 습 니 다.이것 은 처리 과정의 유연성 을 증가 시 켰 다.단, 이 버퍼 에 충분 한 처리 가 필요 한 모든 데 이 터 를 포함 하고 있 는 지 확인 해 야 합 니 다.그리고 더 많은 데이터 가 버퍼 에 읽 힐 때 처리 되 지 않 은 버퍼 데 이 터 를 덮어 쓰 지 않도록 해 야 합 니 다.
차단 및 비 차단 IO
자바 IO 의 각종 흐름 은 막 힌 것 이다.이것 은 읽 기 read () 나 write () 를 호출 할 때 일부 데이터 가 읽 히 거나 데이터 가 완전히 기 록 될 때 까지 이 스 레 드 가 막 힌 다 는 것 을 의미한다.이 라인 은 이 기간 동안 더 이상 어떤 일 도 할 수 없다.
자바 NIO 의 비 차단 모드 는 한 스 레 드 가 특정한 채널 에서 데 이 터 를 읽 어 달라 고 요청 합 니 다. 현재 사용 가능 한 것 만 있 거나 현재 사용 가능 한 데이터 가 없 을 때 아무것도 없습니다.데이터 가 읽 을 수 있 을 때 까지 스 레 드 를 막 는 것 이 아니 라 다른 일 을 계속 할 수 있 습 니 다.
비 차단 쓰기 도 마찬가지다.한 라인 은 어떤 채널 에 데 이 터 를 쓸 것 을 요 청 했 지만, 완전히 쓸 때 까지 기다 리 지 않 았 다. 그리고 이 라인 은 다른 일 을 할 수 있 었 다.
스 레 드 는 차단 되 지 않 은 IO 의 남 은 시간 호출 을 보통 다른 채널 에서 사용 합 니 다. 즉, 하나의 단독 스 레 드 는 현재 여러 개의 입력 과 출력 채널 을 관리 할 수 있 습 니 다.
선택 기
자바 NIO 의 선택 기 는 하나의 단독 스 레 드 로 여러 입력 채널 을 감시 할 수 있 습 니 다. 선택 기의 여러 채널 을 등록 한 다음 에 하나의 단독 스 레 드 '선택' 채널 을 사용 할 수 있 습 니 다. 이미 입력 한 것 은 처리 할 수 있 거나 특정한 채널 이 기록 할 준비 가 되 어 있 습 니 다.이런 선택 체 제 는 하나의 단독 스 레 드 로 하여 금 여러 통 로 를 쉽게 관리 하 게 한다.
NIO 와 IO 는 응용 프로그램의 디자인 에 어떻게 영향 을 줍 니까?
IO 나 NIO 도구 상 자 를 선택 하 더 라 도 프로그램 디자인 의 다음 과 같은 몇 가지 측면 에 영향 을 줄 수 있 습 니 다.
1.        NIO 나 IO 류 의 API 호출
2.        데이터 처리.
3.        데 이 터 를 처리 할 스 레 드 수 입 니 다.
API 호출
물론 NIO 의 API 호출 을 사용 할 때 IO 를 사용 할 때 와 다 르 게 보 이 는 것 도 당연 하 다. 하나의 InputStream 에서 만 바이트 별로 읽 는 것 이 아니 라 데 이 터 는 버퍼 에 먼저 읽 고 거기서 처리 해 야 한다.
데이터 처리
순수한 NIO 디자인 을 사용 하여 IO 디자인 에 비해 데이터 처리 도 영향 을 받는다.
IO 디자인 에서 InputStream 이나 Reader 에서 바이트 별로 읽 습 니 다.텍스트 데이터 기반 줄 흐름 을 처리 하고 있다 고 상상 해 보 세 요. 예 를 들 어:
Name: Anna
Age: 25
Email: [email protected]
Phone: 1234567890
이 텍스트 줄 의 흐름 은 이렇게 처리 할 수 있 습 니 다:
1
2
3
4
5
6
7
8
9
10
11 InputStream input = ... ; // get the InputStream from the client socket     BufferedReader reader = new BufferedReader( new InputStreamReader(input));     String nameLine   = reader.readLine();     String ageLine    = reader.readLine();     String emailLine  = reader.readLine();     String phoneLine  = reader.readLine();
처리 상 태 는 프로그램 이 얼마나 실행 되 는 지 에 따라 결정 되 는 지 주의 하 십시오.다시 말 하면 reader. readLine () 방법 이 돌아 오 면 텍스트 줄 이 다 읽 혔 다 는 것 을 알 수 있 습 니 다. readline () 이 줄 전체 가 다 읽 을 때 까지 막 혔 습 니 다. 이것 이 바로 원인 입 니 다.당신 도 이 줄 에 이름 이 포함 되 어 있다 는 것 을 알 고 있 습 니 다.마찬가지 로 두 번 째 readline () 호출 이 되 돌 아 왔 을 때 이 줄 은 나이 등 을 포함 하고 있다 는 것 을 알 고 있 습 니 다.
보시 다시 피 이 처리 프로그램 은 새로운 데 이 터 를 읽 을 때 만 실행 되 고 모든 데이터 가 무엇 인지 알 수 있 습 니 다.일단 실행 중인 현성 에서 읽 은 일부 데 이 터 를 처리 한 적 이 있 으 면 이 스 레 드 는 데 이 터 를 다시 반환 하지 않 을 것 이다 (대부분 그렇다).다음 그림 에서 도 이 원칙 을 설명 했다.
자바 IO: 차단 흐름 에서 데이터 읽 기
하나의 NIO 실현 은 다 를 것 이다.다음은 간단 한 예 이다.
1
2
3 ByteBuffer buffer = ByteBuffer.allocate( 48 );     int bytesRead = inChannel.read(buffer);
두 번 째 줄 을 주의 하 십시오. 채널 에서 바이트 에서 ByteBuffer 까지 읽 습 니 다.이 방법 이 되 돌 아 왔 을 때, 당신 이 필요 로 하 는 모든 데이터 가 버퍼 안에 있 는 지 알 수 없습니다.이 버퍼 에 바이트 가 포함 되 어 있어 서 처리 하기 가 어렵 다 는 것 을 알 고 있 습 니 다.
첫 번 째 read (buffer) 가 호출 되면 모든 읽 기 버퍼 가 반 줄 이 라 고 상상 해 보 세 요. 예 를 들 어 "Name: An" 입 니 다. 데 이 터 를 처리 할 수 있 습 니까?분명히 안 됩 니 다. 전체 줄 의 데이터 가 캐 시 에 읽 힐 때 까지 기 다 려 야 합 니 다. 그 전에 데이터 에 대한 어떠한 처리 도 의미 가 없습니다.
그래서 이 버퍼 에 충분 한 데 이 터 를 포함 하고 있 는 지 어떻게 알 았 습 니까?됐어, 넌 몰라.발 견 된 방법 은 버퍼 의 데이터 만 볼 수 있 습 니 다.그 결과 데이터 가 그 안에 있 는 지 알 기 전에 버퍼 를 몇 번 검사 해 야 한 다 는 것 이다.이것 은 효율 이 낮 을 뿐만 아니 라 방안 설 계 를 매우 난잡 하 게 할 수 있다.예 를 들 면:
1
2
3
4
5
6
7
8
9
10
11 ByteBuffer buffer = ByteBuffer.allocate( 48 );         int bytesRead = inChannel.read(buffer);         while (! bufferFull(bytesRead) ) {     bytesRead = inChannel.read(buffer);     }
bufferFull () 방법 은 버퍼 에 얼마나 많은 데 이 터 를 읽 었 는 지 추적 하고 실제 또는 가 짜 를 되 돌려 야 합 니 다. 버퍼 가 가득 찼 는 지 에 달 려 있 습 니 다.버퍼 가 처 리 될 준비 가 되 어 있 으 면 꽉 찬 것 으로 여 겨 진 다 는 얘 기다.
버퍼 풀 () 방법 은 버퍼 를 스 캔 하지만 버퍼 풀 () 방법 이 호출 되 기 전에 상태 가 같 아야 합 니 다.없 으 면 다음 버퍼 에 들 어 가 는 데 이 터 를 올 바른 위치 로 읽 을 수 없습니다.이것 은 불가능 하지만 주의해 야 할 또 하나의 문제 이다.
버퍼 가 가득 차 면 처리 할 수 있 습 니 다.만약 그것 이 불만 이 있다 면, 특정한 상황 에서 그 안에 존재 하 는 모든 데 이 터 를 부분적으로 처리 할 수 있 을 것 이다.많은 경우 에는 그렇지 않다.
다음 그림 은 "버퍼 데이터 순환 완료" 를 보 여 줍 니 다.
자바 NIO: 캐 시 영역 에 필요 한 데이터 가 있 을 때 까지 채널 에서 데 이 터 를 읽 습 니 다.
요약
NIO 는 하나의 (또는 몇 개) 단일 라인 으로 여러 채널 (네트워크 연결 이나 파일) 을 관리 할 수 있 습 니 다. 그러나 대 가 는 데 이 터 를 분석 하 는 것 이 하나의 차단 흐름 에서 데 이 터 를 읽 을 때 보다 복잡 할 수 있 습 니 다.
수천 개의 열 린 연결 공존 을 관리 해 야 한다 면 채 팅 서버 와 같은 작은 데이터 만 보 낼 수 있 고 NIO 를 실현 하 는 서버 가 장점 일 수 있 습 니 다.마찬가지 로 P2P 네트워크 와 같은 다른 컴퓨터 에 열 린 연결 을 많이 유지 해 야 한다 면 하나의 단독 스 레 드 로 모든 출구 연결 을 관리 하 는 것 이 장점 일 수 있 습 니 다.다음 그림 과 같은 스 레 드 여러 연결 디자인 방안:
자바 NIO: 단일 회선 관리 다 중 접속
만약 당신 이 매우 높 은 대역 폭 이 더 적은 연결 을 가지 고 있다 면, 한 번 에 대량의 데 이 터 를 보 내 면 전형 적 인 IO 서버 가 가능 한 가장 좋 은 결합 을 이 룰 수 있 을 것 입 니 다.다음 그림 은 전형 적 인 IO 서버 디자인 을 설명 한다.
자바 IO: 전형 적 인 IO 디자인 - 스 레 드 마다 연결 처리

좋은 웹페이지 즐겨찾기