Post

๐ŸฆŠ chap7. ๋ณ‘๋ ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์„ฑ๋Šฅ

chap7. ๋ณ‘๋ ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์„ฑ๋Šฅ

7.1 ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ

์ปฌ๋ ‰์…˜์— parallelStream ์„ ํ˜ธ์ถœํ•˜๋ฉด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด ์ƒ์„ฑ๋œ๋‹ค.

์ด๋Š” ๊ฐ๊ฐ์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ŠคํŠธ๋ฆผ ์š”์†Œ๋ฅผ ์—ฌ๋Ÿฌ ์ฒญํฌ๋กœ ๋ถ„ํ• ํ•œ ์ŠคํŠธ๋ฆผ์ด๋‹ค.

์ˆซ์ž n ์„ ์ธ์ˆ˜๋กœ ๋ฐ›์•„์„œ 1๋ถ€ํ„ฐ n๊นŒ์ง€์˜ ๋ชจ๋“  ์ˆซ์ž์˜ ํ•ฉ๊ณ„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์ž.

1
2
3
4
5
public long sequentialSum(long n) {
	return Stream.iterate(1L, i -> i + 1)
								.limit(n)
								.reduce(0L, Long::sum);
}

์ „ํ†ต์ ์ธ JAVA ์—์„œ๋Š” ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
public long iterativeSum(long n) {
	long result = 0;
	for (long i = 1L; i <= n; i++) {
		result += i;
	}
	return result;
}

n ์ด ์ปค์ง„๋‹ค๋ฉด ์ด ์—ฐ์‚ฐ์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ์ด๋‹ค.

7.1.1 ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ

์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์— parallel ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ธฐ์กด์˜ ํ•จ์ˆ˜ํ˜• ๋ฆฌ๋“€์‹ฑ ์—ฐ์‚ฐ์ด ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.

1
2
3
4
5
6
public long parallelSum(long n) {
	return Stream.iterate(1L, i -> i + 1)
								.limit(n)
								.parallel()
								.reduce(0L, Long::sum);
}

์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์— parallel ์„ ํ˜ธ์ถœํ•ด๋„ ์ŠคํŠธ๋ฆผ ์ž์ฒด๋Š” ์•„๋ฌด ๋ณ€ํ™”๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์ง€๋งŒ,

๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์ดํ›„ ์—ฐ์‚ฐ์ด ๋ณ‘๋ ฌ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•จ์„ ์˜๋ฏธํ•˜๋Š” boolean ํ”Œ๋ž˜๊ทธ๊ฐ€ ์„ค์ •๋œ๋‹ค.

๋ฐ˜๋Œ€๋กœ sequential ๋กœ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
stream.parallel()
			.filter(...)
			.sequential()
			.map(...)
			.parallel()
			.reduce(...)

parallel ๊ณผ sequential ์ค‘ ๋งˆ์ง€๋ง‰์— ํ˜ธ์ถœ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ์— ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

์—ฌ๊ธฐ์—์„œ๋Š” parallel ์ด๋ฏ€๋กœ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ „์ฒด์ ์œผ๋กœ ๋ณ‘๋ ฌ ์‹คํ–‰๋œ๋‹ค.

7.1.2 ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ์ธก์ •

๋ณ‘๋ ฌํ™”๋ฅผ ์ด์šฉํ•˜๋ฉด ์ˆœ์ฐจ๋‚˜ ๋ฐ˜๋ณต์— ๋น„ํ•ด ์„ฑ๋Šฅ์ด ์ข‹์•„์งˆ ๊ฒƒ์ด๋ผ ์ถ”์ธกํ–ˆ์ง€๋งŒ

์†Œํ”„ํŠธ์›จ์–ด ๊ณตํ•™์—์„œ ์ถ”์ธก์€ ์œ„ํ—˜ํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.

ํ•ญ์ƒ ์ธก์ •์„ ํ•˜๋ผ.

์ž๋ฐ” ๋งˆ์ดํฌ๋กœ๋ฒค์น˜๋งˆํฌ ํ•˜๋‹ˆ์Šค (JMH) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ๋ฐฉ์‹์„ ์ง€์›ํ•˜๋ฉฐ ์•ˆ์ •์ ์œผ๋กœ ์ž๋ฐ” ๊ฐ€์ƒ ๋จธ์‹  (JVM)์„ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ๋ฒค์น˜๋งˆํฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(2, jvmArgs={"-Xms4G", "-Xmx4G"})
public class ParallelStreamBenchmark {
	private static final long N = 10_000_000L;

	@Benchmark
	public long sequentialSum() {
		return Stream.iterate(1L, i -> i + 1).limit(N)
								.retduce(0L, Long::sum);
	}

	@TearDown(Level.Invocation)
	public void tearDown() {
		System.gc();
	}
}

๋ฒค์น˜๋งˆํฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋„๋ก ํž™์˜ ํฌ๊ธฐ๋ฅผ ์ถฉ๋ถ„ํ•˜๊ฒŒ ์„ค์ •ํ–ˆ๊ณ 

๋ฒค์น˜๋งˆํฌ๊ฐ€ ๋๋‚  ๋•Œ๋งˆ๋‹ค ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ๊ฐ•์ œํ–ˆ๋‹ค.

์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ JMH ๋ช…๋ น์€ ํ•ซ์ŠคํŒŸ์ด ์ฝ”๋“œ๋ฅผ ์ตœ์ ํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก 20๋ฒˆ์„ ์‹คํ–‰ํ•˜๋ฉฐ

๋ฒค์น˜๋งˆํฌ๋ฅผ ์ค€๋น„ํ•œ ๋‹ค์Œ 20๋ฒˆ์„ ๋” ์‹คํ–‰ํ•ด ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.

์ฆ‰ 20 + 20 ํšŒ ๋ฐ˜๋ณต ์‹คํ–‰ํ•œ๋‹ค.

1
2
3
sequentialSum -> 121.843
iterativeSum -> 3.273
parallelSum -> 603.059

๋ณ‘๋ ฌ ๋ฒ„์ „์ด ์ฟผ๋“œ ์ฝ”์–ด CPU๋ฅผ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•˜๊ณ  ์ˆœ์ฐจ ๋ฒ„์ „์— ๋น„ํ•ด 5๋ฐฐ๋‚˜ ๋Š๋ ธ๋‹ค.

  • ๋ฐ˜๋ณต ๊ฒฐ๊ณผ๋กœ ๋ฐ•์‹ฑ๋œ ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ˆซ์ž๋ฅผ ๋”ํ•˜๋ ค๋ฉด ์–ธ๋ฐ•์‹ฑ์ด ํ•„์š”ํ•˜๋‹ค.
  • ๋ฐ˜๋ณต ์ž‘์—…์€ ๋ณ‘๋ ฌ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋…๋ฆฝ ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค.

2๋ฒˆ์งธ์˜ ์ด์œ ๋กœ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฒญํฌ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

์ˆœ์ฐจ์ฒ˜๋ฆฌ ๋ฐฉ์‹๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅธ ์ ์ด ์—†์–ด ์Šค๋ ˆ๋“œ๋ฅผ ํ• ๋‹นํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๋งŒ ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๋” ํŠนํ™”๋œ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

LongStream.rangeClosed ๋Š” iterate ์— ๋น„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์ด ์žˆ๋‹ค.

  • ๊ธฐ๋ณธํ˜• long ์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ฐ•์‹ฑ, ์–ธ๋ฐ•์‹ฑ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค.
  • ์‰ฝ๊ฒŒ ์ฒญํฌ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋Š” ์ˆซ์ž ๋ฒ”์œ„๋ฅผ ์ƒ์‚ฐํ•œ๋‹ค.
1
2
3
4
5
6
7
@Benchmark
public long rangedSum() {
	return LongStream.rangeClosed(1, N)
									.reduce(0L, Long::sum);
}

rangedSum -> 5.315
1
2
3
4
5
6
7
8
@Benchmark
public long parallelRangedSum() {
	return LongStream.rangeClosed(1, N)
									.parallel()
									.reduce(0L, Long::sum);
}

parallelRangedSum -> 2.677

๊ธฐ์กด์˜ iterate ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ์ƒ์„ฑํ•œ ์ˆœ์ฐจ ๋ฒ„์ „์— ๋น„ํ•ด ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ ์†๋„๊ฐ€ ๋นจ๋ผ์กŒ๊ณ 

์ˆœ์ฐจ ์‹คํ–‰๋ณด๋‹ค ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ๊ฐ–๋Š” ๋ณ‘๋ ฌ ๋ฆฌ๋“€์‹ฑ์„ ๋งŒ๋“ค์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ณ‘๋ ฌํ™”๊ฐ€ ์™„์ „ ๊ณต์งœ๋Š” ์•„๋‹ˆ๋ผ๋Š” ์‚ฌ์‹ค์„ ๊ธฐ์–ตํ•ด๋ผ.

์ŠคํŠธ๋ฆผ์„ ์žฌ๊ท€์ ์œผ๋กœ ๋ถ„ํ• ํ•ด์•ผ ํ•˜๊ณ , ์„œ๋ธŒ์ŠคํŠธ๋ฆผ์„ ์„œ๋กœ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์˜ ๋ฆฌ๋“€์‹ฑ ์—ฐ์‚ฐ์œผ๋กœ ํ• ๋‹นํ•˜๊ณ , ์ด๊ฒƒ๋“ค์„ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ํ•ฉ์ณ์•ผ ํ•œ๋‹ค.

7.1.3 ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์˜ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ๋ฒ•

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•˜๋Š” ๋งŽ์€ ๋ฌธ์ œ๋Š” ๊ณต์œ ๋œ ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ์–ด๋‚œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
public long sideEffectSum(long n) {
	Accumulator accumulator = new Accumulator();
	LongStream.rangeClosed(1, n).forEach(accumulator::add);
	return accumulator.total;
}

public class Accumulator {
	public long total = 0;
	public void add(long value) { total += value; }
}

์ด ์ฝ”๋“œ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์ˆœ์ฐจ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ฐธ์‚ฌ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค.

๋™๊ธฐํ™”๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋‹ค๋ณด๋ฉด ๊ฒฐ๊ตญ ๋ณ‘๋ ฌํ™”๋ผ๋Š” ํŠน์„ฑ์ด ์—†์–ด์ง„๋‹ค.

7.1.4 ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ

  • ํ™•์‹ ์ด ์„œ์ง€ ์•Š์œผ๋ฉด ์ง์ ‘ ์ธก์ •ํ•˜๋ผ.

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด ํ•ญ์ƒ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ๋น ๋ฅธ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

์ ์ ˆํ•œ ๋ฒค์น˜๋งˆํฌ๋กœ ์ง์ ‘ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜๋‹ค.

  • ๋ฐ•์‹ฑ์„ ์ฃผ์˜ํ•˜๋ผ.

์ž๋™ ๋ฐ•์‹ฑ๊ณผ ์–ธ๋ฐ•์‹ฑ์€ ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์š”์†Œ์ด๋‹ค.

์ž๋ฐ” 8์€ ๋ฐ•์‹ฑ ๋™์ž‘์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ์„ ์ œ๊ณตํ•œ๋‹ค.

  • ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์—์„œ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๋Š” ์—ฐ์‚ฐ์ด ์žˆ๋‹ค.

limit ์ด๋‚˜ findFirst ์ฒ˜๋Ÿผ ์š”์†Œ์˜ ์ˆœ์„œ์— ์˜์กดํ•˜๋Š” ์—ฐ์‚ฐ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์—์„œ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋น„์‹ผ ๋น„์šฉ์„ ์น˜๋Ÿฌ์•ผ ํ•œ๋‹ค.

๋Œ€์‹  findAny ๋Š” ์š”์†Œ์˜ ์ˆœ์„œ์™€ ์ƒ๊ด€์—†์ด ์—ฐ์‚ฐํ•˜๋ฏ€๋กœ findFirst ๋ณด๋‹ค ์„ฑ๋Šฅ์ด ์ข‹๋‹ค.

  • ์ŠคํŠธ๋ฆผ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ ์—ฐ์‚ฐ ๋น„์šฉ์„ ๊ณ ๋ คํ•˜๋ผ.

  • ์†Œ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ์—์„œ๋Š” ๋ณ‘๋ ฌํ™” ๊ณผ์ •์—์„œ ์ƒ๊ธฐ๋Š” ๋ถ€๊ฐ€ ๋น„์šฉ์„ ์ƒ์‡„ํ•  ๋งŒํผ ์ด๋“์ด ์—†๋‹ค.

  • ์ŠคํŠธ๋ฆผ์„ ๊ตฌ์„ฑํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์ ์ ˆํ•œ์ง€ ํ™•์ธํ•˜๋ผ.

ArrayList ๋ฅผ LinkedList ๋ณด๋‹ค ํšจ์œจ์ ์œผ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋‹ค.

range ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“  ๊ธฐ๋ณธํ˜• ์ŠคํŠธ๋ฆผ๋„ ์‰ฝ๊ฒŒ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ŠคํŠธ๋ฆผ์˜ ํŠน์„ฑ๊ณผ ํŒŒ์ดํ”„๋ผ์ธ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด ์ŠคํŠธ๋ฆผ์˜ ํŠน์„ฑ์„ ์–ด๋–ป๊ฒŒ ๋ฐ”๊พธ๋Š”์ง€์— ๋”ฐ๋ผ ๋ถ„ํ•ด ๊ณผ์ • ์„ฑ๋Šฅ์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • ์ตœ์ข… ์—ฐ์‚ฐ์˜ ๋ณ‘ํ•ฉ ๊ณผ์ • ๋น„์šฉ์ด ๋น„์‹ธ๋‹ค๋ฉด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์–ป์€ ์„ฑ๋Šฅ ์ด์ต์ด ์„œ๋ธŒ์ŠคํŠธ๋ฆผ์˜ ๋ถ€๋ถ„ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์น˜๋Š” ๊ณผ์ •์—์„œ ์ƒ์‡„๋  ์ˆ˜ ์žˆ๋‹ค.

7.2 ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„์›Œํฌ

ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ณ‘๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์„ ์žฌ๊ท€์ ์œผ๋กœ ์ž‘์€ ์ž‘์—…์œผ๋กœ ๋ถ„ํ• ํ•œ ๋‹ค์Œ

์„œ๋ธŒํ…Œ์Šคํฌ ๊ฐ๊ฐ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์ณ ์ „์ฒด ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค.

7.2.1 RecursiveTask ํ™œ์šฉ

์Šค๋ ˆ๋“œ ํ’€์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด RecursiveTask<R> ์˜ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

RecursiveTask ๋ฅผ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”์ƒ ๋ฉ”์„œ๋“œ compute ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

1
protected abstract R compute();

compute ๋Š” ํƒœ์ŠคํŠธ๋ฅผ ์„œ๋ธŒํƒœ์Šคํฌ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๋กœ์ง๊ณผ

๋” ์ด์ƒ ๋ถ„ํ• ํ•  ์ˆ˜ ์—†์„ ๋•Œ ๊ฐœ๋ณ„ ์„œ๋ธŒํƒœ์ŠคํŠธ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์‚ฐํ•  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ •์˜ํ•œ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ compute ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜์‚ฌ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
if (ํƒœ์ŠคํŠธ๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ž‘๊ฑฐ๋‚˜ ๋” ์ด์ƒ ๋ถ„ํ• ํ•  ์ˆ˜ ์—†์œผ๋ฉด) {
	์ˆœ์ฐจ์ ์œผ๋กœ ํƒœ์ŠคํŠธ ๊ณ„์‚ฐ
} else {
	ํƒœ์Šคํฌ๋ฅผ ๋‘ ์„œ๋ธŒํƒœ์Šคํฌ๋กœ ๋ถ„ํ• 
	ํƒœ์Šคํฌ๊ฐ€ ๋‹ค์‹œ ์„œ๋ธŒํƒœ์Šคํฌ๋กœ ๋ถ„ํ• ๋˜๋„๋ก ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•จ
	๋ชจ๋“  ์„œ๋ธŒํƒœ์Šคํฌ ์—ฐ์‚ฐ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
	๊ฐ ์„œ๋ธŒํƒœ์Šคํฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์นจ
}

์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋ถ„ํ• ์ •๋ณต ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋ณ‘๋ ฌํ™” ๋ฒ„์ „์ด๋‹ค.

7.2.2 ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

  • join ๋ฉ”์„œ๋“œ๋ฅผ ํƒœ์Šคํฌ์— ํ˜ธ์ถœํ•˜๋ฉด ํƒœ์Šคํฌ๊ฐ€ ์ƒ์‚ฐํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ํ˜ธ์ถœ์ž๋ฅผ ๋ธ”๋ก์‹œํ‚จ๋‹ค.

๋”ฐ๋ผ์„œ ๋‘ ์„œ๋ธŒํƒœ์Šคํฌ๊ฐ€ ๋ชจ๋‘ ์‹œ์ž‘๋œ ๋‹ค์Œ์— join ์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ฐ๊ฐ์˜ ์„œ๋ธŒํƒœ์Šคํฌ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ํƒœ์Šคํฌ๊ฐ€ ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์„ฑ๋Šฅ์ด ํ•˜๋ฝํ•œ๋‹ค.

  • RecursiveTask ๋‚ด์—์„œ๋Š” ForkJoinPool ์˜ invoke ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค.

๋Œ€์‹  compute ๋‚˜ fork ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋ผ.

์ˆœ์ฐจ ์ฝ”๋“œ์—์„œ ๋ณ‘๋ ฌ ๊ณ„์‚ฐ์„ ์‹œ์ž‘ํ•  ๋•Œ๋งŒ invoke ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ์„œ๋ธŒํƒœ์Šคํฌ์— fork ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ForkJoinPool ์˜ ์ผ์ •์„ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•œ์ชฝ ์ž‘์—…์—๋Š” fork ๋ณด๋‹ค compute ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ด๋‹ค.

๋‘ ์„œ๋ธŒํƒœ์Šคํฌ์˜ ํ•œ ํƒœ์Šคํฌ์—๋Š” ๊ฐ™์€ ์Šค๋ ˆ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•œ ํƒœ์Šคํฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ด์šฉํ•˜๋Š” ๋ณ‘๋ ฌ ๊ณ„์‚ฐ์€ ๋””๋ฒ„๊น…์ด ์–ด๋ ต๋‹ค.

๋ณดํ†ต stack trace ๋กœ ๋ฌธ์ œ๊ฐ€ ์ผ์–ด๋‚œ ๊ณผ์ •์„ ์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” fork ๋ผ ๋ถˆ๋ฆฌ๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ compute ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋„์›€์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.

  • ๋ฉ€ํ‹ฐ์ฝ”์–ด์— ๋ฌด์กฐ๊ฑด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ˆœ์ฐจ ์ฒ˜๋ฆฌ๋ณด๋‹ค ๋น ๋ฅผ ๊ฑฐ๋ผ๋Š” ์ƒ๊ฐ์„ ๋ฒ„๋ ค๋ผ.

7.2.3 ์ž‘์—… ํ›”์น˜๊ธฐ

์ž‘์—… ํ›”์น˜๊ธฐ ๊ธฐ๋ฒ•์—์„œ๋Š” ForkJoinPool ์˜ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋ฅผ ๊ฑฐ์˜ ๊ณต์ •ํ•˜๊ฒŒ ๋ถ„ํ• ํ•œ๋‹ค.

๊ฐ๊ฐ์˜ ์Šค๋ ˆ๋“œ๋Š” ํ• ๋‹น๋œ ํƒœ์Šคํฌ๋ฅผ ํฌํ•จํ•˜๋Š” ๋”๋ธ” ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด์„œ ์ž‘์—…์ด ๋๋‚  ๋•Œ๋งˆ๋‹ค ํ์˜ ํ—ค๋“œ์—์„œ ๋‹ค๋ฅธ ํƒœ์Šคํฌ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ž‘์—…ํ•œ๋‹ค.

ํ•œ ์Šค๋ ˆ๋“œ๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋ณด๋‹ค ์ž์‹ ์—๊ฒŒ ํ• ๋‹น๋œ ํƒœ์Šคํฌ๋ฅผ ๋” ๋นจ๋ฆฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ• ์ผ์ด ์—†์–ด์ง„ ์Šค๋ ˆ๋“œ๋Š” ์œ ํœด ์ƒํƒœ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ ํ์˜ ๊ผฌ๋ฆฌ์—์„œ ์ž‘์—…์„ ํ›”์ณ์˜จ๋‹ค.

์ž‘์—…์ž์˜ ํ์— ์žˆ๋Š” ํƒœ์Šคํฌ๋ฅผ ๋‘ ๊ฐœ์˜ ์„œ๋ธŒ ํƒœ์Šคํฌ๋กœ ๋ถ„ํ• ํ–ˆ์„ ๋•Œ,

๋‘˜ ์ค‘ ํ•˜๋‚˜์˜ ํƒœ์Šคํฌ๋ฅผ ๋‹ค๋ฅธ ์œ ํœด ์ž‘์—…์ž๊ฐ€ ํ›”์ณ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

์ฃผ์–ด์ง„ ํƒœ์Šคํฌ๋ฅผ ์ˆœ์ฐจ ์‹คํ–‰ํ•  ๋‹จ๊ณ„๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ์ด ๊ณผ์ •์„ ์žฌ๊ท€์ ์œผ๋กœ ๋ฐ˜๋ณตํ•œ๋‹ค.

7.3 Spliterator ์ธํ„ฐํŽ˜์ด์Šค

์ž๋ฐ” 8์€ Spliterator ๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์ด๋Š” ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ณต์ž๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค.

1
2
3
4
5
6
public interface Spliterator<T> {
	boolean tryAdvance(Consumer<? super ?> action);
	Spliterator<T> trySplit();
	long estimateSize();
	int characteristics();
}
  • T๋Š” Spliterator ์—์„œ ํƒ์ƒ‰ํ•˜๋Š” ์š”์†Œ์˜ ํ˜•์‹์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
  • tryAdvance ๋ฉ”์„œ๋“œ๋Š” ์š”์†Œ๋ฅผ ์†Œ๋น„ํ•˜๋ฉฐ ํƒ์ƒ‰ํ•  ์š”์†Œ๊ฐ€ ๋‚จ์•„์žˆ์œผ๋ฉด true ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • trySplit. ๋ฉ”์„œ๋“œ๋Š” ์ผ๋ถ€ ์š”์†Œ๋ฅผ ๋ถ„ํ• ํ•ด์„œ ๋‘ ๋ฒˆ์งธ Spliterator ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • Spliterator ์—์„œ๋Š” estimateSize ๋ฉ”์„œ๋“œ๋กœ ํƒ์ƒ‰ํ•  ์š”์†Œ ์ˆ˜ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

7.3.1 ๋ถ„ํ•  ๊ณผ์ •

์ŠคํŠธ๋ฆผ์„ ์—ฌ๋Ÿฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ณผ์ •์€ ์žฌ๊ท€์ ์œผ๋กœ ์ผ์–ด๋‚œ๋‹ค.

trySplit ์˜ ๊ฒฐ๊ณผ๊ฐ€ null ์ด ๋  ๋•Œ๊นŒ์ง€ ์ด ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

Spliterator ํŠน์„ฑ

Spliterator ๋Š” characteristics ๋ผ๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋„ ์ •์˜ํ•œ๋‹ค.

์ด๋Š” ์ž์ฒด์˜ ํŠน์„ฑ ์ง‘ํ•ฉ์„ ํฌํ•จํ•˜๋Š” int ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • ORDERED : ์ •ํ•ด์ง„ ์ˆœ์„œ๊ฐ€ ์žˆ์–ด ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค.
  • DISTINCT : x.equals(y) ๋Š” ํ•ญ์ƒ false ์ด๋‹ค.
  • SORTED : ๋ฏธ๋ฆฌ ์ •์˜๋œ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฅธ๋‹ค.
  • SIZED : ํฌ๊ธฐ๊ฐ€ ์•Œ๋ ค์ง„ ์†Œ์Šค๋กœ Spliterator ๋ฅผ ์ƒ์„ฑํ•ด์„œ estimatedSize() ๋Š” ์ •ํ™•ํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • NON-NULL : ํƒ์ƒ‰ํ•  ๋ชจ๋“  ์š”์†Œ๋Š” null ์ด ์•„๋‹ˆ๋‹ค.
  • IMMUTABLE : ๋ชจ๋“  ์†Œ์Šค๋Š” ๋ถˆ๋ณ€์ด๋‹ค.
  • CONCURRENT : ๋™๊ธฐํ™” ์—†์ด ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ์†Œ์Šค๋ฅผ ๋™์‹œ์— ๊ณ ์น  ์ˆ˜ ์žˆ๋‹ค.
  • SUBSIZED : ์ž์‹  ๋ฐ ๋ชจ๋“  ํ•˜์œ„ Spliterator ๋Š” SIZED ์ด๋‹ค.

7.3.2 ์ปค์Šคํ…€ Spliterator ๊ตฌํ˜„ํ•˜๊ธฐ

๋ฌธ์ž์—ด์˜ ๋‹จ์–ด ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋‹จ์ˆœํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์ž.

๋‹ค์Œ์€ ๋ฐ˜๋ณต ๋ฒ„์ „์ด๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
public int countWordsIteratively(String s) {
	int counter = 0;
	boolean lastSpace = true;
	for (char c : s.toCharArray()) {
		if (Character.isWhitespace(c)) {
			lastSpace = true;
		} else {
			if (lastSpace) counter++;
			lastSpace = false;
		}
	}
}

ํ•จ์ˆ˜ํ˜•์œผ๋กœ ๋‹จ์–ด ์ˆ˜๋ฅผ ์„ธ๋Š” ๋ฉ”์„œ๋“œ ์žฌ๊ตฌํ˜„ํ•˜๊ธฐ

์šฐ์„  String ์„ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.

1
2
Stream<Character> stream = IntStream.range(0, SENTENCE.length())
																			.mapToObj(SENTENCE::charAt);

์ง€๊ธˆ๊นŒ์ง€ ๋ฐœ๊ฒฌํ•œ ๋‹จ์–ด ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” int ๋ณ€์ˆ˜์™€

๋งˆ์ง€๋ง‰ ๋ฌธ์ž๊ฐ€ ๊ณต๋ฐฑ์ด์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ธฐ์–ตํ•˜๋Š” boolean ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

์ด๋“ค์„ ์บก์Šํ™”ํ•˜๋Š” ์ƒˆ๋กœ์šด ํด๋ž˜์Šค WordCounter ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class WordCounter {
	private final int counter;
	private final boolean lastSpace;

	public WordCounter(int counter, boolean lastSpace) {
		this.counter = counter;
		this.lastSpace = lastSpace;
	}

	public WordCounter accumulate(Character c) {
		if (Character.isWhitespace(c)) {
			return lastSpace ? this : new WordCounter(counter, true);
		} else {
			return lastSpace ? new WordCounter(counter + 1, false) : this;
		}
	}

	public WordCounter combine(WordCounter wordCounter) {
		return new WordCounter(counter + wordCounter.counter, wordCounter.lastSpace);
	}

	public int getCounter() {
		return counter;
	}
}

์ŠคํŠธ๋ฆผ์„ ํƒ์ƒ‰ํ•˜๋ฉด์„œ ์ƒˆ๋กœ์šด ๋ฌธ์ž๋ฅผ ์ฐพ์„ ๋•Œ๋งˆ๋‹ค accumulate ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

์ƒˆ๋กœ์šด ๋น„๊ณต๋ฐฑ ๋ฌธ์ž๋ฅผ ํƒ์ƒ‰ํ•œ ํ›„ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๊ฐ€ ๊ณต๋ฐฑ์ด๋ฉด counter ๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.

combine ์€ ๋ฌธ์ž์—ด ์„œ๋ธŒ ์ŠคํŠธ๋ฆผ์„ ์ฒ˜๋ฆฌํ•œ WordCounter ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์นœ๋‹ค.

์ด์ œ ์ŠคํŠธ๋ฆผ์˜ ๋ฆฌ๋“€์‹ฑ ์—ฐ์‚ฐ์„ ์ง๊ด€์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
8
private int countWords(Stream<Character> stream) {
	WordCounter wordCounter = stream.reduce(new WordCounter(0, true),
																					WordCounter::accumulate,
																					WordCounter::combine);
	return wordCounter.getCounter();
}

-> Found 19 words

WordCounter ๋ณ‘๋ ฌ๋กœ ์ˆ˜ํ–‰ํ•˜๊ธฐ

1
2
3
countWords(stream.parallel())

-> Found 25 words

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค.

์›๋ž˜ ๋ฌธ์ž์—ด์„ ์ž„์˜์˜ ์œ„์น˜์—์„œ ๋‘˜๋กœ ๋‚˜๋ˆ„๋‹ค๋ณด๋‹ˆ ์˜ˆ์ƒ์น˜ ๋ชปํ•˜๊ฒŒ ํ•˜๋‚˜์˜ ๋‹จ์–ด๋ฅผ ๋‘˜๋กœ ๊ณ„์‚ฐํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹จ์–ด๊ฐ€ ๋๋‚˜๋Š” ์œ„์น˜์—์„œ๋งŒ ๋ถ„ํ• ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋ ค๋ฉด ๋‹จ์–ด ๋์—์„œ ๋ฌธ์ž์—ด์„ ๋ถ„ํ• ํ•˜๋Š” ๋ฌธ์ž Spliterator ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class WordCounterSpliterator implements Spliterator<Character> {
	private final String string;
	private int currentChar = 0;
	public WordCounterSpliterator(String string) {
		this.string = string;
	}

	// ํ˜„์žฌ ๋ฌธ์ž๋ฅผ ์†Œ๋น„ํ•˜๊ณ  ์†Œ๋น„ํ•  ๋ฌธ์ž๊ฐ€ ๋‚จ์•„์žˆ์œผ๋ฉด true ๋ฅผ ๋ฆฌํ„ด
	@Override
	public boolean tryAdvance(Consumer<? super Character> action) {
		action.accept(string.charAt(currentChar++));
		return currentChar < string.length();
	}

	@Override
	public Spliterator<Character> trySplit() {
		int currentSize = string.length() - currentChar;
		if (currentSize < 10) return null;
		
		for (int splitPos = currentSize / 2 + currentChar; splitPost < string.length(); splitPos++) {
			if (Character.isWhitespace(string.charAt(splitPos))) {
				Spliterator<Character> spliterator =
						new WordCounterSpliterator(string.substring(currentChar, splitPos));
				currentChar = splitPost;
				return spliterator;
			}
		}
		return null;
	}
	
	@Override
	public long estimateSize() {
		return string.length() - currentChar;
	}

	@Override
	public int characteristics() {
		return ORDERED + SIZED + SUBSIZED + NON-NULL + IMMUTABLE;
	}
}
  • tryAdvance ๋Š” ํ˜„์žฌ ์ธ๋ฑ์Šค์˜ ๋ฌธ์ž๋ฅผ Consumer ์— ์ œ๊ณตํ•œ ํ›„ ์ธ๋ฑ์Šค๋ฅผ ์ฆ๊ฐ€ํ•œ๋‹ค.

์ƒˆ๋กœ์šด ์ปค์„œ ์œ„์น˜๊ฐ€ ์ „์ฒด ๋ฌธ์ž์—ด ๊ธธ์ด๋ณด๋‹ค ์ž‘์œผ๋ฉด true ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ

์ด๋Š” ๋ฐ˜๋ณต ํƒ์ƒ‰ํ•  ๋ฌธ์ž๊ฐ€ ๋‚จ์•„์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

  • trySplit ์€ ๋ฐ˜๋ณต๋  ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋ถ„ํ• ํ•˜๋Š” ๋กœ์ง์„ ํฌํ•จ, ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ฉ”์„œ๋“œ์ด๋‹ค.

๋ถ„ํ•  ๋™์ž‘์„ ์ค‘๋‹จํ•  ํ•œ๊ณ„๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

์‹ค์ „ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋„ˆ๋ฌด ๋งŽ์€ ํƒœ์Šคํฌ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋„๋ก ๋” ๋†’์€ ํ•œ๊ณ„๊ฐ’์„ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

๋‚จ์€ ๋ฌธ์ž ์ˆ˜๊ฐ€ ํ•œ๊ณ„๊ฐ’ ์ดํ•˜๋ฉด null ์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋ถ„ํ• ์„ ์ค‘์ง€ํ•œ๋‹ค.

๋ถ„ํ• ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํŒŒ์‹ฑํ•  ๋ฌธ์ž์—ด ์ฒญํฌ ์ค‘๊ฐ„ ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„ํ• ํ•˜๋„๋ก ์ง€์‹œํ•œ๋‹ค.

  • ํƒ์ƒ‰ํ•ด์•ผ ํ•  ์š”์†Œ์˜ ๊ฐœ์ˆ˜ estimatedSize ๋Š” ํŒŒ์‹ฑํ•  ๋ฌธ์ž์—ด ์ „์ฒด ๊ธธ์ด์™€ ๋ฐ˜๋ณต์ค‘์ธ ์œ„์น˜์˜ ์ฐจ ์ด๋‹ค.

  • characteristic ๋ฉ”์„œ๋“œ๋Š” ์ด Spliterator ์˜ ํŠน์„ฑ์„ ํฌํ•จํ•œ๋‹ค.

WordCounterSpliterator ํ™œ์šฉ

์ด์ œ ์ด๋ฅผ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
Spliterator<Charater> spliterator = new WordCounterSpliterator(SENTENCE);
Stream<Character> stream = StreamSupport.stream(spliterator, true);

-> Found 19 words

์ด์ œ ๊ธฐ๋Œ€ํ•˜๋Š” ์ถœ๋ ฅ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”๋‹ค.

This post is licensed under CC BY 4.0 by the author.