Written by
Poogle
on
on
Modern Java in Action - Ch.1
참고: 책 - Modern Java in Action
Java 8
이전
- 코어 중 하나만 사용, 나머지 코어는 유휴 idle 상태로 두거나, 운영체제나 바이러스 검사 프로그램과 프로세스 파워를 나눠서 사용
이후
- 멀티 코어 CPU 대중화 -> 영향
- 나머지 코어를 활용하려면 스레드를 사용해야 함
- 병렬 실행 환경을 쉽게 관리 & 에러를 덜 발생시키려고 함
- 간결한 코드 & 멀티코어 프로세서의 쉬운 활용
- ⏩ 스트림 API
스트림을 쓰면
synchronized
를 쓰지 않아도 된다?synchornized
키워드 사용하면 lock 걸어서 그 동안 다른 쓰레드가 실행하지 못하게 됨- 멀티코어 CPU의 각 코어는 별도의 캐시를 포함하고 있는데, 락을 쓰면 이런 캐시가 동기화 되어야 함
- 그러다보면 속도가 느린 캐시 일관성 프로토콜 인터코어 통신(cache-coherency-protocol intercore communication)이 이루어짐
- ⏩ 메서드에 코드를 전달하는 기법
- 동작 파라미터화 구현 가능 -> 함수형 프로그래밍
- ⏩ 인터페이스의 디폴트 메서드
Java 9에서는…
- 리액티브 프로그래밍이라는 병렬 실행 기법을 지원
- 고성능 병렬 시스템에서 특히 인기를 얻고 있는 RxJava(리액티브 스트림 툴킷)를 표준적인 방식으로 지원
Java 8 설계의 밑바탕을 이루는 세 가지 프로그래밍 개념
빅데이터 🌬 프로그래밍 언어 생태계
1. 스트림 처리
- 스트림: 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임
- 입력 스트림에서 데이터를 한 개씩 읽고 -> 출력 스트림으로 한 개씩 기록
- 기존에는 한 번에 한 항목 처리 -> 작업을 고수준으로 추상화해서 일련의 스트림으로 만들어 처리할 수 있음
- 스트림 파이프라인을 이용해서 입력 부분을 여러 CPU 코어에 쉽게 할당할 수 잇음
- 쓰레드 안 쓰고도 병렬성 가능!
2. 동작 파라미터화로 메서드에 코드 전달하기
- 코드 일부를 API로 전달
- 메서드를 다른 메서드의 인수로 넘겨주는 기능 제공
- 스트림 API는 연산의 동작을 파라미터화할 수 있는 코드를 전달한다는 사상에 기초
3. 병렬성과 공유 가변 데이터
- 스트림 메서드로 전달하는 코드는 다른 코드와 동시에 실행되더라도 안전하게 실행될 수 있어야 함
- 다른 코드와 동시에 실행하더라도 안전하게 실행할 수 있는 코드를 만들려면? -> 공유된 가변 데이터(shared mutable data)에 접근하지 않아야 함
자바 함수, 메서드와 람다를 일급 시민으로
- 자바 8에서는 함수를 새로운 값의 형식으로 추가함 -> 멀티코어에서 병렬 프로그래밍을 활용할 수 있는 스트림과 연계될 수 있도록
- 프로그래밍 언어의 핵심: 값을 바꾸는 것
- 일급 값(일급 시민) -> java 에서는 Object(객체)
- 파라미터로 전달할 수 있음
- 반환값(return value)로 사용할 수 있음
- 변수나 데이터 구조 안에 담을 수 있음
- 할당에 사용된 이름과 관계없이 고유한 구별이 가능
- 이급 시민: 전달할 수 없는 구조체(메서드, 클래스)
- 일급 값(일급 시민) -> java 에서는 Object(객체)
- ⏩ 메서드를 일급 시만으로 만들면?
- 메서드 참조:
::
이 메서드를 값으로 사용하라는 의미
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isHidden();
}
});
//메서드 참조 활용
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
- 람다(또는 익명함수)를 포함하여 함수도 값으로 취급할 수 있음
- 메서드를 값으로 전달하기 -> 한 번만 사용할 메서드도?
- ⏩ 따로 정의를 구현할 필요 없음, 람다로 구현
스트림
- 컬렉션을 만들고 활용
- for-each 루프를 이용해서 반복: 외부 반복
- 스트림 API 이용하면 라이브러리 내부에서 모든 데이터 처리: 내부 반복
- 컬렉션을 이용할 때
- 서로 다른 CPU 코어에 작업을 각각 할당 -> 처리 시간 줄임
멀티 스레딩의 어려움
- 자바 8은 스트림 API(java.util.stream)로 컬렉션을 처리하면서 발생하는 모호함과 반복적인 코드 문제, 그리고 멀티코어 활용 어려움 문제 해결
- 기존 컬렉션에서 데이터 처리할 때 반복되는 패턴 -> 라이브러리에서 제공
- filtering
- extracting
- grouping
- 이러한 동작들을 쉽게 병렬화
- 스트림 API와 컬렉션 API
- 컬렉션: 어떻게 데이터를 저장하고 접근할지
- 스트림: 데이터에 어떤 계산을 할 것인지, 스트림 내의 요소를 쉽게 병렬로 처리할 수 있는 환경을 제공하는 것이 핵심
- 컬렉션을 필터링 할 수 있는 가장 빠른 방법
- ✅ 컬렉션을 -> 스트림으로 바꾸고 -> 병렬로 처리한 다음 -> 리스트로 다시 복원
디폴트 메서드와 자바 모듈
- 자바 9의 모듈 시스템은 모듈을 정의하는 문법 제공
- 패키지 모음을 포함하는 모듈을 정의할 수 있음 -> JAR 같은 컴포넌트에 구조를 적용할 수 있음, 문서화와 모듈 확인 작업이 용이해짐
- 자바 8에서는 인터페이스를 쉽게 바꿀 수 있도록 디폴트 메서드 지원
- 기존의 구현을 고치지 않고도 이미 공개된 인터페이스를 변경하려면?
- ⏩ 구현 클래스에서 구현하지 않아도 되는 메서드를 인터페이스에 추가할 수 있는 기능 제공
// ex. sort
default void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}
- List 인터페이스에 default 메서드가 추가되어서 이 sort 메서드는 정적 메서드인 Collection.sort를 호출한다.
- 디폴트 sort를 구현하지 않아도 된다!
함수형 프로그래밍에서 가져온 다른 유용한 아이디어
Optional
- 자바 8에서는 NPE(NullPointer Exception)을 피할 수 있도록 도와주는
Optional<T>
클래스를 제공 - 형식 시스템을 이용해서 어떤 변수에 값이 없을 때 어떻게 처리할 지 명시할 수 있음
(구조적 structural) 패턴 매칭 기법
- if-then-else가 아닌 케이스로 정의하는 수학과 함수형 프로그래밍의 기능을 의미