item 48 Jung inchul - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
Effective Java 3e ์์ดํ 48๋ฅผ ์์ฝํ ๋ด์ฉ ์ ๋๋ค.
์ฃผ๋ฅ ์ธ์ด ์ค, ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ ์ธก๋ฉด์์ ์๋ฐ๋ ํญ์ ์์๊ฐ๋ค.
- 1996๋ โ ์ค๋ ๋, ๋๊ธฐํ, wait/notify ์ง์
- ์๋ฐ 5 โ ๋์์ฑ ์ปฌ๋ ์ ์ธ java.util.concurrent ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์คํ์(Executor) ํ๋ ์์ํฌ ์ง์
- ์๋ฐ 7 โ ๊ณ ์ฑ๋ฅ ๋ณ๋ ฌ ๋ถํด ํ๋ ์์ํฌ์ธ ํฌํฌ-์กฐ์ธ(fork-join) ํจํค์ง ์ถ๊ฐ
- ์๋ฐ 8 โ parallel ๋ฉ์๋๋ง ํ ๋ฒ ํธ์ถํ๋ฉด ํ์ดํ๋ผ์ธ์ ๋ณ๋ ฌ ์คํํ ์ ์๋ ์คํธ๋ฆผ ์ง์
๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ํ ๋๋ ์์ ์ฑ(Safety
)๊ณผ ์๋ต๊ฐ๋ฅ(liveness
) ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ ์จ์ผ ํ๋๋ฐ ๋ณ๋ ฌ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ํ๋ก๊ทธ๋๋ฐ์์๋ ๋ค๋ฅผ ๋ฐ ์๋ค.
์์ดํ 45์์ ๋ค๋ฃจ์๋ ๋ฉ๋ฅด์ผ ์์๋ฅผ ์์ฑํ๋ ํ๋ก๊ทธ๋จ์ ๋ค์ ์ดํด๋ณด์. (๋ฉ๋ฅด์ผ ์ M(n)์ 2n -1 ํํ์ธ ์ซ์๋ฅผ ๋งํ๋ค. ๋ฉ๋ฅด์ผ ์์๋ ๋ฉ๋ฅด์ผ ์ ์ค ์์์ธ ๊ฒ๋ค์ ๊ฐ๋ฆฌํจ๋ค.)
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);
}
์ํ๊น๊ฒ๋ ์ด ํ๋ก๊ทธ๋จ์ ์๋ฌด๊ฒ๋ ์ถ๋ ฅํ์ง ๋ชปํ๋ฉด์ CPU
๋ 90%
๋ ์ก์๋จน๋ ์ํ๊ฐ ๋ฌดํํ ๊ณ์๋๋ค.
ํ๋ก๊ทธ๋จ์ด ์ด๋ ๊ฒ ๋๋ ค์ง ์์ธ์ ์ฌ์ค ์ด์ด์๊ฒ๋ ์คํธ๋ฆผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ด ํ์ดํ๋ผ์ธ
์ ๋ณ๋ ฌํ
ํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์๋ด์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ด๋ค. ํ๊ฒฝ์ด ์๋ฌด๋ฆฌ ์ข๋๋ผ๋ ๋ฐ์ดํฐ ์์ค๊ฐ Stream.iterate
๊ฑฐ๋ ์ค๊ฐ ์ฐ์ฐ์ผ๋ก limit
๋ฅผ ์ฐ๋ฉด ํ์ดํ๋ผ์ธ ๋ณ๋ ฌํ๋ก๋ ์ฑ๋ฅ ๊ฐ์ ์ ๊ธฐ๋ํ ์ ์๋ค.
์์ ํ๋๋ฅผ ๊ณ์ฐํ๋ ๋น์ฉ์ด ๋๋ต ๊ทธ ์ด์ ๊น์ง์ ์์ ์ ๋ถ๋ฅผ ๊ณ์ฐํ ๋น์ฉ์ ํฉ์น ๊ฒ๋งํผ ๋ ๋ค๋ ๋ป์ด๋ค. ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๋ง๊ตฌ์ก์ด๋ก ๋ณ๋ ฌํ
ํ๋ฉด ์ ๋๋ค. ์ฑ๋ฅ์ด ์คํ๋ ค ๋์ฐํ๊ฒ ๋๋น ์ง ์๋ ์๋ค.
๋์ฒด๋ก ์คํธ๋ฆผ์ ์์ค๊ฐ ArrayList
, HashMap
, HashSet
, ConcurrentHashMap
์ ์ธ์คํด์ค๊ฑฐ๋ ๋ฐฐ์ด
, int ๋ฒ์
, long ๋ฒ์
์ผ ๋ ๋ณ๋ ฌํ์ ํจ๊ณผ๊ฐ ๊ฐ์ฅ ์ข๋ค. ์ด ์๋ฃ๊ตฌ์กฐ๋ค์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ํ๋ ํฌ๊ธฐ๋ก ์ ํํ๊ณ ์์ฝ๊ฒ ๋๋ ์ ์์ด์ ์ผ์ ๋ค์์ ์ค๋ ๋
์ ๋ถ๋ฐฐํ๊ธฐ์ ์ข๋ค๋ ํน์ง์ด ์๋ค. ๋๋๋ ์์
์ Spliterator
๊ฐ ๋ด๋นํ๋ฉฐ, Spliterator
๊ฐ์ฒด๋ Stream
์ด๋ Iterable
์ spliterator
๋ฉ์๋๋ก ์ป์ด์ฌ ์ ์๋ค.
์ด ์๋ฃ๊ตฌ์กฐ๋ค์ ๋ ๋ค๋ฅธ ์ค์ํ ๊ณตํต์ ์ ์์๋ค์ ์์ฐจ์ ์ผ๋ก ์คํํ ๋์ ์ฐธ์กฐ ์ง์ญ์ฑ(locality of reference)
์ด ๋ฐ์ด๋๋ค๋ ๊ฒ์ด๋ค.
์ฐธ์กฐ ์ง์ญ์ฑ์ด๋? ํ๋ฒ ์ฐธ์กฐํ ๋ฐ์ดํฐ๋ ๋ค์ ์ฐธ์กฐ๋ ๊ฐ๋ฅ์ฑ์ด ๋๊ณ ์ฐธ์กฐ๋ ๋ฐ์ดํฐ ์ฃผ๋ณ์ ๋ฐ์ดํฐ ์ญ์ ๊ฐ์ด ์ฐธ์กฐ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ์ฑ์ง์ด๋ค.
ํ์ง๋ง ์ฐธ์กฐ๋ค์ด ๊ฐ๋ฆฌํค๋ ์ค์ ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ์๋ก ๋จ์ด์ ธ ์์ ์ ์๋๋ฐ, ๊ทธ๋ฌ๋ฉด ์ฐธ์กฐ ์ง์ญ์ฑ์ด ๋๋น ์ง๋ค. ์ฐธ์กฐ ์ง์ญ์ฑ์ด ๋ฎ์ผ๋ฉด ์ค๋ ๋๋ ๋ฐ์ดํฐ๊ฐ ์ฃผ ๋ฉ๋ชจ๋ฆฌ์์ ์บ์ ๋ฉ๋ชจ๋ฆฌ๋ก ์ ์ก๋์ด ์ค๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ๋๋ถ๋ถ ์๊ฐ์ ๋ฉํ๋ ๋ณด๋ด๊ฒ ๋๋ค.
์ฐธ์กฐ ์ง์ญ์ฑ์ด ๊ฐ์ฅ ๋ฐ์ด๋ ์๋ฃ๊ตฌ์กฐ๋ ๊ธฐ๋ณธ ํ์
์ ๋ฐฐ์ด
์ด๋ค. ๊ธฐ๋ณธ ํ์
๋ฐฐ์ด์์๋ (์ฐธ์กฐ๊ฐ ์๋) ๋ฐ์ดํฐ ์์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ฐ์ํด์ ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ด๋ค.
(min, max, count, sum), anyMatch, allMatch, noneMatch์ฒ๋ผ ์กฐ๊ฑด์ ๋ง์ผ๋ฉด ๋ฐ๋ก ๋ฐํ๋๋ ๋ฉ์๋๋ ๋ณ๋ ฌํ์ ์ ํฉํ๋ค. ๋ฐ๋ฉด, ๊ฐ๋ณ ์ถ์๋ฅผ ์ํํ๋ Stream์ collect ๋ฉ์๋๋ ๋ณ๋ ฌํ์ ์ ํฉํ์ง ์๋ค.
๊ฐ๋ณ ์ถ์ ๋ฉ์๋๋? ๊ฒฐ๊ณผ๊ฐ์ ๊ฐ๊ณตํ์ฌ ์๋ก์ด ๋ฆฌ์คํธ๋ก ์ถ์ถํ๋ ๋ฉ์๋์ด๋ค.
List<String> list = Arrays.asList("Mike", "Nicki", "John");
String s = list.stream().collect(StringBuilder::new,
(sb, s1) -> sb.append(" ").append(s1),
(sb1, sb2) -> sb1.append(sb2.toString())).toString();
System.out.println(s);
์ง์ ๊ตฌํํ Stream, Iterable, Collection์ด ๋ณ๋ ฌํ์ ์ด์ ์ ์ ๋๋ก ๋๋ฆฌ๊ฒ ํ๊ณ ์ถ๋ค๋ฉด spliterator
๋ฉ์๋๋ฅผ ๋ฐ๋์ ์ฌ์ ์ํ๊ณ ๊ฒฐ๊ณผ ์คํธ๋ฆผ์ ๋ณ๋ ฌํ ์ฑ๋ฅ์ ๊ฐ๋ ๋๊ฒ ํ
์คํธํ๋ผ.
์คํธ๋ฆผ์ ์๋ชป ๋ณ๋ ฌํํ๋ฉด (์๋ต ๋ถ๊ฐ๋ฅผ ํฌํจํด) ์ฑ๋ฅ์ด ๋๋น ์ง ๋ฟ๋ง ์๋๋ผ ๊ฒฐ๊ณผ ์์ฒด๊ฐ ์๋ชป๋๊ฑฐ๋ ์์ ๋ชปํ ๋์์ด ๋ฐ์ํ ์ ์๋ค. ๊ฒฐ๊ณผ๊ฐ ์๋ชป๋๊ฑฐ๋ ์ค๋์ํ๋ ๊ฒ์ ์์ ์คํจ(safety failure
)๋ผ ํ๋ค.
Stream ๋ช
์ธ๋ ์ด๋ ์ฌ์ฉ๋๋ ํจ์ ๊ฐ์ฒด์ ๊ดํ ์์คํ ๊ท์ฝ์ ์ ์ํด๋จ๋ค. ์์ปจ๋ Stream
์ reduce
์ฐ์ฐ์ ๊ฑด๋ค์ง๋ accumulator(๋์ ๊ธฐ)์ combiner(๊ฒฐํฉ๊ธฐ) ํจ์๋ ๋ฐ๋์ ๊ฒฐํฉ ๋ฒ์น์ ๋ง์กฑํ๊ณ (associative), ๊ฐ์ญ๋ฐ์ง ์๊ณ (non-interfeing), ์ํ๋ฅผ ๊ฐ์ง ์์์ผ(stateless) ํ๋ค
์ถ๋ ฅ ์์๋ฅผ ์์ฐจ ๋ฒ์ ์ฒ๋ผ ์ ๋ ฌํ๊ณ ์ถ๋ค๋ฉด ์ข
๋จ ์ฐ์ฐ forEach
๋ฅผ forEachOrdered
๋ก ๋ฐ๊ฟ์ฃผ๋ฉด ๋๋ค.
์ฌ์ง์ด ๋ฐ์ดํฐ ์์ค ์คํธ๋ฆผ์ด ํจ์จ์ ์ผ๋ก ๋๋ ์ง๊ณ , ๋ณ๋ ฌํํ๊ฑฐ๋ ๋นจ๋ฆฌ ๋๋๋ ์ข ๋จ ์ฐ์ฐ์ ์ฌ์ฉํ๊ณ , ํจ์ ๊ฐ์ฒด๋ค๋ ๊ฐ์ญํ์ง ์๋๋ผ๋ ํ์ดํ๋ผ์ธ์ด ์ํํ๋ ์ง์ง ์์ ์ด ๋ณ๋ ฌํ์ ๋๋ ์ถ๊ฐ ๋น์ฉ์ ์์ํ์ง ๋ชปํ๋ค๋ฉด ์ฑ๋ฅ ํฅ์์ ๋ฏธ๋ฏธํ ์ ์๋ค.
์คํธ๋ฆผ ๋ณ๋ ฌํ๋ ์ค์ง ์ฑ๋ฅ ์ต์ ํ ์๋จ์์ ๊ธฐ์ตํด์ผ ํ๋ค. ๋ค๋ฅธ ์ต์ ํ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณ๊ฒฝ ์ ํ๋ก ๋ฐ๋์ ์ฑ๋ฅ์ ํ ์คํธํ์ฌ ๋ณ๋ ฌํ๋ฅผ ์ฌ์ฉํ ๊ฐ์น๊ฐ ์๋์ง ํ์ธํด์ผ ํ๋ค. (์์ดํ 67)
์กฐ๊ฑด์ด ์ ๊ฐ์ถฐ์ง๋ฉด parallel
๋ฉ์๋ ํธ์ถ ํ๋๋ก ๊ฑฐ์ ํ๋ก์ธ์ ์ฝ์ด ์์ ๋น๋กํ๋ ์ฑ๋ฅ ํฅ์์ ๋ง๋ฝํ ์ ์๋ค.
static long pi(long n) {
return LongStream.rangeClosed(2, n)
.parallel()
.mapToObj(BigInteger::valueOf)
.filter(i -> i.isProbablePrime(50))
.count();
}
๋ฌด์์ ์๋ค๋ก ์ด๋ค์ง ์คํธ๋ฆผ์ ๋ณ๋ ฌํํ๋ ค๊ฑฐ๋ TreadLocalRandom
(ํน์ ๊ตฌ์์ธ Random
)๋ณด๋ค๋ SplittableRandom
์ธ์คํด์ค๋ฅผ ์ด์ฉํ์
๊ณ์ฐ๋ ์ฌ๋ฐ๋ก ์ํํ๊ณ ์ฑ๋ฅ๋ ๋นจ๋ผ์ง ๊ฑฐ๋ผ๋ ํ์ ์์ด๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ๋ณ๋ ฌํ๋ ์๋์กฐ์ฐจ ํ์ง ๋ง๋ผ. ์คํธ๋ฆผ์ ์๋ชป ๋ณ๋ ฌํ
ํ๋ฉด ํ๋ก๊ทธ๋จ์ ์ค๋์ํ๊ฒ ํ๊ฑฐ๋ ์ฑ๋ฅ์ ๊ธ๊ฒฉํ ๋จ์ด๋จ๋ฆฐ๋ค. ๋ณ๋ ฌํ
ํ๋ ํธ์ด ๋ซ๋ค๊ณ ๋ฏฟ๋๋ผ๋, ์์ ํ์ ์ฝ๋๊ฐ ์ฌ์ ํ ์ ํํ์ง ํ์ธํ๊ณ ์ด์ ํ๊ฒฝ๊ณผ ์ ์ฌํ ์กฐ๊ฑด์์ ์ํํด๋ณด๋ฉฐ ์ฑ๋ฅ์งํ๋ฅผ ์ ์ฌํ ๊ด์ฐฐํ๋ผ. ๊ทธ๋์ ๊ณ์ฐ๋ ์ ํํ๊ณ ์ฑ๋ฅ๋ ์ข์์ก์์ด ํ์คํด์ก์ ๋ ์ค์ง ๊ทธ๋ด ๋๋ง ๋ณ๋ ฌํ ๋ฒ์ ์ฝ๋๋ฅผ ์ด์ ์ฝ๋์ ๋ฐ์ํด๋ผ