item 48 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

item 48

์‹œ์Šคํ…œ ๋ณ‘๋ ฌํ™”๋Š” ์ฃผ์˜ํ•ด์„œ ์ ์šฉํ•˜๋ผ

ํ•ต์‹ฌ์ •๋ฆฌ

๊ณ„์‚ฐ๋„ ์˜ฌ๋ฐ”๋กœ ์ˆ˜ํ–‰ํ•˜๊ณ  ์„ฑ๋Šฅ๋„ ๋นจ๋ผ์งˆ ๊ฑฐ๋ผ๋Š” ํ™›์‹  ์—†์ด๋Š” ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”๋Š” ์‹œ๋„์กฐ์ฐจ ํ•˜์ง€ ๋ง๋ผ. ์ŠคํŠธ๋ฆผ์„ ์ž˜๋ชป ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์„ ์˜ค์ž‘๋™ํ•˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์„ฑ๋Šฅ์„ ๊ธ‰๊ฒฉํžˆ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค. ๋ณ‘๋ ฌํ™” ํ•˜๋Š”๊ฒŒ ๋‚ซ๋‹ค๊ณ  ๋ฏฟ๋”๋ผ๋„ ์šด์˜ํ™˜๊ฒฝ๊ณผ ์œ ์‚ฌํ•œ ์กฐ๊ฑด์—์„œ ์ˆ˜ํ–‰ํ•ด๋ณด๋ฉฐ ์„ฑ๋Šฅ์ง€ํ‘œ๋ฅผ ๊ณ„์† ๊ด€์ฐฐํ•˜๋ผ. ์ •๋ง์ •๋ง ์„ฑ๋Šฅ์ด ์ข‹์•„์ง„๊ฒŒ ํ™•์‹คํ•ด์กŒ์„ ๋•Œ, ๊ทธ๋Ÿด๋•Œ๋งŒ ๋ณ‘๋ ฌํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.

์ž๋ฐ”๋Š” ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์•ž์žฅ ์„œ์„œ ์ง€์›ํ•ด์คฌ๋‹ค. ์ž๋ฐ” 8๋ถ€ํ„ฐ๋Š” ์•„์˜ˆ parallel ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ณ‘๋ ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ŠคํŠธ๋ฆผ์„ ์ง€์›ํ•ด์ค€๋‹ค. ์ด์ฒ˜๋Ÿผ ์ž๋ฐ”๋กœ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ธฐ๋Š” ์ ์  ์‰ฌ์›Œ์ง€์ง€๋งŒ,์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ณ  ๋น ๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ์ผ์€ ์—ฌ์ „ํžˆ ์—ฌ๋Ÿฝ๋‹ค.

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ์˜ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ, 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์„ ์“ฐ๋ฉด ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”๋กœ๋Š” ์„ฑ๋Šฅ๊ฐœ์„ ์„ ํ•  ์ˆ˜ ์—†๋‹ค.
  • ์ด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒˆ๋กญ๊ฒŒ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ฅผ ์ฐพ์„ ๋•Œ ๋งˆ๋‹ค ๊ทธ ์ด์ „๊นŒ์ง€์˜ ์›์†Œ ์ „๋ถ€๋ฅผ ๊ณ„์‚ฐํ•œ ๋น„์šฉ์„ ํ•ฉ์นœ๊ฒƒ ๋งŒํผ ๋“ ๋‹ค (!!) โ†’ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งˆ๊ตฌ์žก์ด๋กœ ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด ์„ฑ๋Šฅ์ด ๋”์ฐํ•ด์ง„๋‹ค.

๋ณ‘๋ ฌ ์ˆ˜ํ–‰ ํšจ์œจ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ์š”์†Œ๋“ค

  1. ์ŠคํŠธ๋ฆผ์˜ ์†Œ์Šค๊ฐ€ ArrayList, HashMap, HashSet, ConcurrentHashMap์˜ ์ธ์Šคํ„ด์Šค๊ฑฐ๋‚˜ ๋ฐฐ์—ด, ๋ฒ”์œ„, long ๋ฒ”์œ„์ผ ๋–„ ๋ณ‘๋ ฌํ™”์˜ ํšจ๊ฐ€๊ฐ€ ๊ฐ€์žฅ ์ข‹๋‹ค.
    • ์—ด๊ฑฐํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋“ค ๋ชจ๋‘ ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ์›ํ•˜๋Š” ํฌ๊ธฐ๋กœ ์ •ํ™•ํ•˜๊ณ  ์†์‰ฝ๊ฒŒ ๋‚˜์ˆ  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ์„ ๋‹ค์ˆ˜์˜ ์Šค๋ ˆ๋“œ์— ๋ถ„๋ฐฐํ•˜๊ธฐ ์ข‹๋‹ค.

      โ†’ ๋‚˜๋ˆ„๋Š” ์ผ์€ Spliterator๊ฐ€ ๋‹ด๋‹นํ•˜๊ณ , Stream์ด๋‚˜ Iterable ์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

    • ์ฐธ์กฐ ์ง€์—ญ์„ฑ ๋˜ํ•œ ๋›ฐ์–ด๋‚˜๋‹ค. โ†’ ์›์†Œ์˜ ์ฐธ์กฐ๋“ค์ด ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†ํ•ด์„œ ์ €์žฅ์ด ๋˜์–ด์žˆ๋‹ค. โ†’ ์ฐธ์กฐ์ง€์—ญ์„ฑ์ด ๋–จ์–ด์ง€๋ฉด ์Šค๋ ˆ๋“œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ(๋Š๋ฆผ) ์บ์‹œ ๋ฉ”๋ชจ๋ฆฌ๋กœ ์ „์†ก๋˜์–ด ์˜ค๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์–ด ์‹œ๊ฐ„ ๋‚ญ๋น„๊ฐ€ ์‹ฌํ•˜๋‹ค. โ†’ ๋ณ‘๋ ฌํ™”๋ฅผ ํ•  ๋•Œ ๋ฉ์–ด๋ฆฌ(๋ฒŒํฌ)๋กœ ๋–ผ ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์ฐธ์กฐ์ง€์—ญ์„ฑ์ด ์ •๋ง ์ค‘์š”ํ•˜๋‹ค!

  2. ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ข…๋‹จ ์—ฐ์‚ฐ ๋™์ž‘ ๋ฐฉ์‹๋„ ๋ณ‘๋ ฌ ์ˆ˜ํ–‰ ํšจ์œจ์— ์˜ํ•ญ์„ ์ค€๋‹ค.
    • ๋ณ‘๋ ฌํ™”์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์—ฐ์‚ฐ์€ 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์„ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ์•…์˜ ์„ฑ๋Šฅ์ด ๋‚˜์˜จ๋‹ค!
โš ๏ธ **GitHub.com Fallback** โš ๏ธ