item 48 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
์์คํ ๋ณ๋ ฌํ๋ ์ฃผ์ํด์ ์ ์ฉํ๋ผ
๊ณ์ฐ๋ ์ฌ๋ฐ๋ก ์ํํ๊ณ ์ฑ๋ฅ๋ ๋นจ๋ผ์ง ๊ฑฐ๋ผ๋ ํ์ ์์ด๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ๋ณ๋ ฌํ๋ ์๋์กฐ์ฐจ ํ์ง ๋ง๋ผ. ์คํธ๋ฆผ์ ์๋ชป ๋ณ๋ ฌํํ๋ฉด ํ๋ก๊ทธ๋จ์ ์ค์๋ํ๊ฒ ํ๊ฑฐ๋ ์ฑ๋ฅ์ ๊ธ๊ฒฉํ ๋จ์ด๋จ๋ฆฐ๋ค. ๋ณ๋ ฌํ ํ๋๊ฒ ๋ซ๋ค๊ณ ๋ฏฟ๋๋ผ๋ ์ด์ํ๊ฒฝ๊ณผ ์ ์ฌํ ์กฐ๊ฑด์์ ์ํํด๋ณด๋ฉฐ ์ฑ๋ฅ์งํ๋ฅผ ๊ณ์ ๊ด์ฐฐํ๋ผ. ์ ๋ง์ ๋ง ์ฑ๋ฅ์ด ์ข์์ง๊ฒ ํ์คํด์ก์ ๋, ๊ทธ๋ด๋๋ง ๋ณ๋ ฌํ๋ฅผ ์ฌ์ฉํ๋ผ.
์๋ฐ๋ ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์์ฅ ์์ ์ง์ํด์คฌ๋ค. ์๋ฐ 8๋ถํฐ๋ ์์ parallel ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ํ์ดํ๋ผ์ธ์ ๋ณ๋ ฌ ์คํํ ์ ์๋ ์คํธ๋ฆผ์ ์ง์ํด์ค๋ค. ์ด์ฒ๋ผ ์๋ฐ๋ก ๋์์ฑ ํ๋ก๊ทธ๋จ์ ์์ฑํ๊ธฐ๋ ์ ์ ์ฌ์์ง์ง๋ง,์ด๋ฅผ ์ฌ๋ฐ๋ฅด๊ณ ๋น ๋ฅด๊ฒ ์์ฑํ๋ ์ผ์ ์ฌ์ ํ ์ฌ๋ฝ๋ค.
//๋ฉ๋ฅด์ผ ์์๋ฅผ ๊ตฌํ๋ ์๋ ์ฝ๋
public static void main(String[] args) {
primes().map(p -> TWO.pow(p.intValueExact()).subtract(ONE))
.filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
.forEach(System.out::println);
}
//parallel์ ์ด์ฉํด ๋ณธ๋ค
public static void main(String[] args) {
primes().map(p -> TWO.pow(p.intValueExact()).subtract(ONE))
.parallel()
.filter(mersenne -> mersenne.isProbablePrime(50))
.limit(20)
.forEach(System.out::println);
}
static Stream<BigInteger> primes() {
return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}
parallel์ ์ด์ฉํด์ ๋ณ๋ ฌ๋ก ์คํํ์ผ๋๊น ์๋๊ฐ ๋ ๋นจ๋ผ์ก๊ฒ ์ง? ๋ผ๊ณ ์๊ฐํ ์ ์๋๋ฐ ์ฑ๋ฅ ํฅ์์ด ์ด๋ฃจ์ด์ง ์์๊ณ CPU์ 90% ์ฌ์ฉํ๋ ์ํ๋ง ๋ฌดํํ ๋ฐ๋ณต๋๋ค. ์ ์ด๋ฐ ์ผ์ด ๋ฐ์ํ๋๊ฑธ๊น?
- ์คํธ๋ฆผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ด ํ์ดํ๋ผ์ธ์ ๋ณ๋ ฌํํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์๋ด์ง ๋ชปํ๋ค.
- ์์ค๊ฐ Stream.iterate์ด๋ limit์ ์ฐ๋ฉด ํ์ดํ๋ผ์ธ ๋ณ๋ ฌํ๋ก๋ ์ฑ๋ฅ๊ฐ์ ์ ํ ์ ์๋ค.
- ์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ์๋กญ๊ฒ ๋ฉ๋ฅด์ผ ์์๋ฅผ ์ฐพ์ ๋ ๋ง๋ค ๊ทธ ์ด์ ๊น์ง์ ์์ ์ ๋ถ๋ฅผ ๊ณ์ฐํ ๋น์ฉ์ ํฉ์น๊ฒ ๋งํผ ๋ ๋ค (!!) โ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๋ง๊ตฌ์ก์ด๋ก ๋ณ๋ ฌํํ๋ฉด ์ฑ๋ฅ์ด ๋์ฐํด์ง๋ค.
- ์คํธ๋ฆผ์ ์์ค๊ฐ ArrayList, HashMap, HashSet, ConcurrentHashMap์ ์ธ์คํด์ค๊ฑฐ๋ ๋ฐฐ์ด, ๋ฒ์, long ๋ฒ์์ผ ๋ ๋ณ๋ ฌํ์ ํจ๊ฐ๊ฐ ๊ฐ์ฅ ์ข๋ค.
-
์ด๊ฑฐํ ์๋ฃ๊ตฌ์กฐ๋ค ๋ชจ๋ ๋ค ๋ฐ์ดํฐ๋ฅผ ์ํ๋ ํฌ๊ธฐ๋ก ์ ํํ๊ณ ์์ฝ๊ฒ ๋์ ์ ์๊ธฐ ๋๋ฌธ์ ์ผ์ ๋ค์์ ์ค๋ ๋์ ๋ถ๋ฐฐํ๊ธฐ ์ข๋ค.
โ ๋๋๋ ์ผ์ Spliterator๊ฐ ๋ด๋นํ๊ณ , Stream์ด๋ Iterable ์์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
-
์ฐธ์กฐ ์ง์ญ์ฑ ๋ํ ๋ฐ์ด๋๋ค. โ ์์์ ์ฐธ์กฐ๋ค์ด ๋ฉ๋ชจ๋ฆฌ์ ์ฐ์ํด์ ์ ์ฅ์ด ๋์ด์๋ค. โ ์ฐธ์กฐ์ง์ญ์ฑ์ด ๋จ์ด์ง๋ฉด ์ค๋ ๋๋ ๋ฐ์ดํฐ๊ฐ ์ฃผ ๋ฉ๋ชจ๋ฆฌ์์(๋๋ฆผ) ์บ์ ๋ฉ๋ชจ๋ฆฌ๋ก ์ ์ก๋์ด ์ค๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ด ์๊ฐ ๋ญ๋น๊ฐ ์ฌํ๋ค. โ ๋ณ๋ ฌํ๋ฅผ ํ ๋ ๋ฉ์ด๋ฆฌ(๋ฒํฌ)๋ก ๋ผ ์ค๊ธฐ ๋๋ฌธ์ ์ฐธ์กฐ์ง์ญ์ฑ์ด ์ ๋ง ์ค์ํ๋ค!
-
- ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์ข
๋จ ์ฐ์ฐ ๋์ ๋ฐฉ์๋ ๋ณ๋ ฌ ์ํ ํจ์จ์ ์ํญ์ ์ค๋ค.
- ๋ณ๋ ฌํ์ ๊ฐ์ฅ ์ ํฉํ ์ฐ์ฐ์ min, max, count, sum ์ผ๋ก, ์ถ์ฝํด์ ์์ฑ๋ ํํ๋ก ์ ๊ณตํ๋ค.
- anyMatch, allMatch, noneMatch์ฒ๋ผ ์กฐ๊ฑด์ ๋ง์ผ๋ฉด ๋ฒ๋ก ๋ฐํ๋ผ๋ ๋ฉ์๋๋ ์ ํฉํ๋ค.
- ๋จ, ์ปฌ๋ ์ ์ ํฉ์น๊ฑฐ๋ ํ๋ฉฐ ๊ฐ์ ๋ณ๊ฒฝํ๋ ์ฐ์ฐ๋ค(๊ฐ๋ณ์ถ์, stream.collect) ๋ ์ ํฉํ์ง ์๋ค.
- ์์ฐจ์ ์ธ ์ฐ์ฐ์ด๋ผ๋ฉด ๋ณ๋ ฌ ์ํ์ ํจ๊ณผ๋ ๋จ์ด์ง ์ ๋ฐ์ ์๋ค.
์คํธ๋ฆผ์ ์๋ชป ๋ณ๋ ฌํํ๋ฉด ์ฑ๋ฅ์ด ๋๋น ์ง ๋ฟ๋ง ์๋๋ผ ๊ฒฐ๊ณผ ์์ฒด๊ฐ ์๋ชป๋๊ฑฐ๋ ์์ ๋ชปํ ๋์์ด ๋ฐ์ํ ์ ์๋ค. (safety failure, ์์ ์คํจ)
โ ์์ ์คํจ๋ ๋ณ๋ ฌ ํ์ดํ๋ผ์ธ์ด ์ฌ์ฉํ๋ mappers, filters ํน์ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ง๋ ํจ์ ๊ฐ์ฒด๊ฐ ๋ช ์ธ๋๋ก ๋์ํ์ง ์์ ๋ ๋ฒ์ด์ง ์ ์๋ค. (์ด๋ฐ result๊ฐ ๋์ค๊ฒ ์ง? ํ์ผ๋ ์ค๋ฅ๋ ์๋๋ฐ ์์ํ๋ result์ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค)
โ๋ณ๋ ฌ์ฒ๋ฆฌ๋ก ๊ตฌํ ๊ฐ๋ค์ด ์์๊ฐ ์ฌ๋ฐ๋ฅด์ง ์๋ค๋ฉด forEach ๋ง๊ณ forEachOrdered ๋ฅผ ์ฌ์ฉํ์.
โ ๋ฐ์ดํฐ ์์ค ์คํธ๋ฆผ์ด ์ ๋๋ ์ง๊ณ , ๋ณ๋ ฌํํ๊ฑฐ๋ ๋นจ๋ฆฌ ๋๋๋ ์ข ๋จ ์ฐ์ฐ์ ์ฌ์ฉํ๋ ๋ฑ ๋ชจ๋ ์กฐ๊ฑด์ด ์๋ฒฝํ๋๋ผ๋ ํ์ดํ๋ผ์ธ์ด ์ํํ๋ ์ง์ง ์์ ์ด ๋ณ๋ ฌํ์ ๋๋ ์ถ๊ฐ ๋น์ฉ์ ์์ํ์ง ๋ชฉํ๋ค๋ฉด ์ฑ๋ฅ ํฅ์์ ๋ฏธ๋ฏธํ๋ค.
โ์คํธ๋ฆผ ๋ณ๋ ฌํ๋ ์ค์ง ์ฑ๋ฅ ์ต์ ํ ์๋จ์ด๋ค. ์ฑ๋ฅ ํ ์คํธ๋ฅผ ํ์๋ก ์งํํ๊ณ , ์ด์ ์์คํ ๊ณผ ํก์ฌํ ํ๊ฒฝ์์ ํ ์คํธ ํ๋๊ฒ ์ข๋ค. ์๋ชป๋ ํ์ดํ๋ผ์ธ ํ๋๊ฐ ์์คํ ์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ฑ๋ฅ๊น์ง ์ ์ํฅ์ ์ค ์ ์๋ค.
์คํธ๋ฆผ ๋ณ๋ ฌํ๋ฅผ ์ธ ์ผ์ด ์ ์ด์ง ๊ฒ์ฒ๋ผ ๋๊ปด์ง ๊ฒ์ด๋ค. ๊ทธ๊ฑด ์ง์ง ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ด๋ค. ์คํธ๋ฆผ์ ์ผ๋ง๋ ๋ง์ด ์ฌ์ฉํ๋ ์ฝ๋์ด๋, ์คํธ๋ฆผ ๋ณ๋ ฌํ๊ฐ ํจ๊ณผ๋ฅผ ๋ณด๋ ๊ฒฝ์ฐ๋ ๋ง์ง ์๋ค.
// n๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ์์์ ๊ฐ์๋ฅผ ๊ณ์ฐํ๋ ์ฝ๋
static long pi(long n) {
return LongStream.rangeClosed(2, n)
.mapToObj(BigInteger::valueOf)
.filter(i -> i.isProbablePrime(50))
.count();
}
// parallel ์ฌ์ฉ
static long pi(long n) {
return LongStream.rangeClosed(2, n)
.parallel()
.mapToObj(BigInteger::valueOf)
.filter(i -> i.isProbablePrime(50))
.count();
}
์กฐ๊ฑด์ด ์ ๊ฐ์ถฐ์ง ์์ ๊ฐ์ ์ฝ๋์์๋ ๋ณ๋ ฌํ์ ํจ๊ณผ๋ฅผ ๋ณผ ์ ์์ง๋ง, n์ด ์ปค์ง๋ฉด ์ด ๋ฐฉ์์ผ๋ก ๊ณ์ฐํ๋ ๊ฑด ์ข์ง ๋ชปํ๋ค. ๋ ํจ์จ์ ์ธ ๋ ๋จธ์ ๊ณต์ ์๊ณ ๋ฆฌ์ฆ์ด ์๊ธฐ ๋๋ฌธ.
- ๋ฌด์์ ์๋ค๋ก ์ด๋ค์ง ์คํธ๋ฆผ์ ๋ณ๋ ฌํ ํ๋ ค๋ฉด SplittableRandom ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ์. ๋ณ๋ ฌํํ๋ฉด ์ฑ๋ฅ์ด ์ ํ์ผ๋ก ์ฆ๊ฐํ๊ธฐ ๋๋ฌธ.
- ThreadLocalRandom์ ๋จ์ผ ์ฐ๋ ๋์์ ์ฐ๊ณ ์ ๋ง๋ค์ด์ก๊ธฐ ๋๋ฌธ์ SplittableRandom ๋งํผ ๋น ๋ฅด์ง ์๋ค.
- ๊ทธ๋ฅ Random์ ์ฌ์ฉํ๋ฉด ์ต์ ์ ์ฑ๋ฅ์ด ๋์จ๋ค!