item 80 incheol - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

์Šค๋ ˆ๋“œ๋ณด๋‹ค๋Š” ์‹คํ–‰์ž, ํƒœ์Šคํฌ, ์ŠคํŠธ๋ฆผ์„ ์• ์šฉํ•˜๋ผ

java.util.concurrent ํŒจํ‚ค์ง€๋Š” ์‹คํ–‰์ž ํ”„๋ ˆ์ž„์›Œํฌ๋ผ๊ณ  ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์˜ ์œ ์—ฐํ•œ ํƒœ์Šคํฌ ์‹คํ–‰ ๊ธฐ๋Šฅ์„ ๋‹ด๊ณ  ์žˆ๋‹ค.

// ์ž‘์—… ํ๋ฅผ ์ƒ์„ฑํ•˜๋‹ค. 
ExcutorService exec  = Executors.newSingleThreadExcutor();

// ๋‹ค์Œ์€ ์ด Excutor์— ์‹คํ–‰ํ•  ํƒœ์Šคํฌ(task; ์ž‘์—…)๋ฅผ ๋„˜๊ธฐ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
exec.execute(runnable);

// ๋‹ค์Œ์€ Excutor๋ฅผ ์šฐ์•„ํ•˜๊ฒŒ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค(์ด ์ž‘์—…์ด ์‹คํŒจํ•˜๋ฉด VM ์ž์ฒด๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค)
exec.shutdown();

์‹คํ–‰์ž ์„œ๋น„์Šค์˜ ๊ธฐ๋Šฅ์€ ์ด ์™ธ์—๋„ ๋งŽ๋‹ค.

์‹คํ–‰์ž ์„œ๋น„์Šค์˜ ์ฃผ์š” ๊ธฐ๋Šฅ

  • ํŠน์ • ํƒœ์Šคํฌ๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
  • ํƒœ์Šคํฌ ๋ชจ์Œ ์ค‘ ์•„๋ฌด๊ฒƒ ํ•˜๋‚˜(invokeAny ๋ฉ”์„œ๋“œ) ํ˜น์€ ๋ชจ๋“  ํƒœ์Šคํฌ(invokeALL ๋ฉ”์„œ๋“œ)๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
  • ์‹คํ–‰์ž ์„œ๋น„์Šค๊ฐ€ ์ข…๋ฃŒํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค(awaitTermination ๋ฉ”์„œ๋“œ)
  • ์™„๋ฃŒ๋œ ํƒœ์Šคํฌ๋“ค์˜ ๊ฒฐ๊ณผ๋ฅผ ์ฐจ๋ก€๋กœ ๋ฐ›๋Š”๋‹ค(ExecutorCompletionService ์ด์šฉ)
  • ํƒœ์Šคํฌ๋ฅผ ํŠน์ • ์‹œ๊ฐ„์— ํ˜น์€ ์ฃผ๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๊ฒŒ ํ•œ๋‹ค(ScheculedThread PoolExecutor ์ด์šฉ)

๊ทธ ์™ธ ๊ธฐ๋Šฅ

  • ํ๋ฅผ ๋‘˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ฐ„๋‹จํžˆ ๋‹ค๋ฅธ ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ์ข…๋ฅ˜์˜ ์‹คํ–‰์ž ์„œ๋น„์Šค(์Šค๋ ˆ๋“œ ํ’€)๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋œ๋‹ค.
  • ํ‰๋ฒ”ํ•˜์ง€ ์•Š์€ ์‹คํ–‰์ž๋ฅผ ์›ํ•œ๋‹ค๋ฉด ThreadPoolExecutor ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค. ์ด ํด๋ž˜์Šค๋กœ๋Š” ์Šค๋ ˆ๋“œ ํ’€ ๋™์ž‘์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ex) new ThreadPoolExecutor(1, 3 ,3, SECONDS, queue);
  • ์ž‘์€ ํ”„๋กœ๊ทธ๋žจ์ด๋‚˜ ๊ฐ€๋ฒผ์šด ์„œ๋ฒ„๋ผ๋ฉด Executors.newCachedThreadPool์„ ์‚ฌ์šฉํ•˜๋ผ. ํŠน๋ณ„ํžˆ ์„ค์ •ํ•  ๊ฒŒ ์—†๊ณ  ์ผ๋ฐ˜์ ์ธ ์šฉ๋„์— ์ ํ•ฉํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.
  • ๋ฌด๊ฑฐ์šด ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„์—์„œ๋Š” ์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜๋ฅผ ๊ณ ์ „ํ•œ Executors.newFixedThreadPool์„ ์„ ํƒํ•˜๊ฑฐ๋‚˜ ์™„์ „ํžˆ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋Š” ThreadPoolExecutor๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ํ›จ์”ฌ ๋‚ซ๋‹ค.

์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค

์ž‘์—… ํ๋ฅผ ์†์ˆ˜ ๋งŒ๋“œ๋Š” ์ผ์€ ์‚ผ๊ฐ€์•ผ ํ•˜๊ณ , ์Šค๋ ˆ๋“œ๋ฅผ ์ง์ ‘ ๋‹ค๋ฃจ๋Š” ๊ฒƒ๋„ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ผ๊ฐ€์•ผ ํ•œ๋‹ค. ์Šค๋ ˆ๋“œ๋ฅผ ์ง์ ‘ ๋‹ค๋ฃจ๋ฉด Thread๊ฐ€ ์ž‘์—… ๋‹จ์œ„์™€ ์ˆ˜ํ–‰ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์—ญํ• ์„ ๋ชจ๋‘ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค. ๋ฐ˜๋ฉด ์‹คํ–‰์ž ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ์ž‘์—… ๋‹จ์œ„์™€ ์‹คํ–‰ ๋งค์ปค๋‹ˆ์ฆ˜์ด ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด์„œ ์˜๋ฏธ๊ฐ€ ๋ช…ํ™•ํ•˜๋‹ค.

  • Runnable : ์ธ์ž๋ฅผ ๋ฐ›์ง€ ์•Š๊ณ  ๋ฆฌํ„ด๊ฐ’์ด ์—†๋‹ค.
  • Callable : ์ธ์ž๋ฅผ ๋ฐ›์ง€ ์•Š์œผ๋ฉฐ, ํŠน์ • ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. ๋˜ํ•œ call() ๋ฉ”์†Œ๋“œ ์ˆ˜ํ–‰ ์ค‘ Exception์„ ๋ฐœ์ƒํ•œ๋‹ค.

ForkJoinTask

์ž๋ฐ” 7์ด ๋˜๋ฉด์„œ ์‹คํ–‰์ž ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํฌํฌ-์กฐ์ธ ํƒœ์Šคํฌ๋ฅผ ์ง€์›ํ•˜๋„๋ก ํ™•์žฅ๋˜์—ˆ๋‹ค. ํฌํฌ-์กฐ์ธ ํƒœ์Šคํฌ, ์ฆ‰ ForkJoinTask์˜ ์ธ์Šคํ„ด์Šค๋Š” ์ž‘์€ ํ•˜์œ„ ํƒœ์Šคํฌ๋กœ ๋‚˜๋‰  ์ˆ˜ ์ด๊ณ , ForkJoinPool์„ ๊ตฌ์„ฑํ•˜๋Š” ์Šค๋ ˆ๋“œ๋“ค์ด ์ด ํƒœ์Šคํฌ๋“ค์„ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ์ผ์„ ๋จผ์ € ๋๋‚ธ ์Šค๋ ˆ๋“œ๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์˜ ๋‚จ์€ ํƒœ์Šคํฌ๋ฅผ ๊ฐ€์ ธ์™€ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ํฌํฌ-์กฐ์ธ ํƒœ์Šคํฌ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๊ณ  ํŠœ๋‹ํ•˜๊ธฐ๋ž€ ์–ด๋ ค์šด ์ผ์ด์ง€๋งŒ, ํฌํฌ-์กฐ์ธ ํ’€์„ ์ด์šฉํ•ด ๋งŒ๋“  ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•˜๋ฉด ์ ์€ ๋…ธ๋ ฅ์œผ๋กœ ๊ทธ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  ํฌํฌ-์กฐ์ธ์— ์ ํ•ฉํ•œ ํ˜•ํƒœ์˜ ์ž‘์—…์ด์–ด์•ผ ํ•œ๋‹ค.

์ฐธ์กฐ