모던 자바인액션 1장
자바 8 이후 부터는 간결한 코드, 멀티코어 프로세서의 쉬운 활용이라는 요구사항에 맞춰 진화하였다.
왜 아직도 자바는 변화하는가?
기술의 흐름에 맞추지 못하는 언어는 다른 경쟁 언어에 비해 도태될 수 밖에 없다.
하드웨어가 발전함에 따라 빅데이터를 다루게 되었고, 멀티코어 컴퓨터나 컴퓨팅 클러스터를 이용해서 빅데이터를 효과적으로 처리할 필요성이 커졌다. 그러나 자바 8이전 버전에서는 이러한 요구사항을 만족시킬 수 없었다.
자바 8 설계 컨셉
스트림 처리
유닉스 계열의 운영체제에서는 '|' 키워드로 다른 프로그램에게 데이터를 전달할 수 있다. 이런 방식은 간결함과 동시에 병렬성을 수행할 수 있는데, 다음과 같은 예제를 보자.
cat file1 file2 | tr "[A-Z]" "[a-z]" | sort | tail -3
cat과 tr를 병렬로 처리하여 왼쪽부터 오른쪽으로 순서대로 데이터의 흐름을 처리하기 때문에, 데이터 의존관계가 있는 작업의 총 시간을 줄일 수 있다.
자바의 스트림 처리는 순차 방식과 병렬 방식으로 나뉘는데, 병렬 방식의 코드는 다음과 같이 작성한다.
import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.parallelStream().filter((Apple a) -> a.getWeight() > 150).collect(toList());
그런데 어떻게 분할하며, 공유 데이터의 동기화는 어떻게 맞추는지 궁금하다.
자바 8에서는 라이브러리에서 하나의 큰 filter를 작은 filter들로 나누어 처리한다. 또한 filter들은 서로의 데이터를 침범하지 않기 때문에 굳이 동기화를 해주지 않아도 된다.
또한 업데이트는 기존 버전과의 호환이 되어야 한다. 자바 8에서는 디폴트 메서드로 클래스들을 쉽게 업데이트할 수 있었는데, 인터페이스를 상속하는 다른 수많은 인터페이스들을 전부 업데이트하기란 시간이 너무 소모된다.
따라서 인터페이스에 구현하지 않아도 되는 메서드를 추가하는 기능을 제공하여, 가장 상위의 인터페이스에 적용하여 문제를 해결하였다.
default void sort(Comparator<? super E> c){
Collections.sort(this, c);
}
동작 파라미터화로 메서드에 코드 전달하기
C언어의 함수 포인터와 유사하다. 다음의 C코드를 보자.
int add(int a, int b)
{
return a + b;
}
int calc(int a, int b, int (*op_func)(int, int))
{
return op_func(a, b);
}
계산 함수에서는 필요에 따라 add 이외의 함수를 구현하여 연산을 다르게 할 수 있다.
자바에서는 이러한 기능을 지원하지 않았기 때문에 간단한 코드를 작성하더라도 상속을 해야했고 코드의 양이 늘어날 수 밖에 없었다.
일급 객체란 객체 값을 자유롭게 전달할 수 있는 객체들을 의미한다. e.g.) integer형 데이터, String형 데이터
이급 객체란 자유롭게 전달할 수 없는 객체들을 의미한다. e.g.) 함수, 클래스
자바 8에서는 함수를 일급 객체로 취급하도록 변경하였는데, 함수를 변수 취급하여 다루는 방식을 함수형 프로그래밍이라 한다.
이렇게 되면 요구사항이 변경되더라도, 호출하는 함수 객체만 갈아끼우면 되기에 변경이 편리하다.
익명 함수란 함수의 이름이 정해지지는 않았지만 함수의 동작을 하는 기능을 의미한다.
예를 들어 (int x) -> x + 1, x라는 변수를 x + 1하여 반환하는 "간단한 코드를 간단하게 작성할 수 있다."
병렬성과 공유 가변 데이터
자바 코드의 동기화 방식은 synchronized란 키워드로 정의할 수 있다. 클래스에 synchronized란 키워드를 붙여 스레드에서 공유 데이터를 동기화할 수 있는데, 문제는 다음과 같다.
1. 프로그래머가 임계 영역을 생각하여 동기화 로직을 작성해야 한다.
- 공유되지 않는 데이터들은 임계영역에 넣을 필요가 없기 때문이다.
2. 동기화는 느리다.
- 데이터를 순차적으로 처리해야 하기 때문에 한 쪽에서 작업하면, 다른 쪽은 멈춰있을 수 밖에 없다.
자바 8에서는 스트림 API가 병렬적으로 나눠서 수행해주고 동시에 각각마다 상호작용이 일어나지 않게 해주기 때문에 프로그래머가 고민할 영역이 줄어들었다.