item 81 leekyunghee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

wait์™€ notify ๋ณด๋‹ค๋Š” ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์• ์šฉํ•˜๋ผ

์“ฐ๋ ˆ๋“œ์˜ ์‹คํ–‰์ˆœ์„œ์˜ ๋™๊ธฐํ™”

์“ฐ๋ ˆ๋“œ์˜ ์‹คํ–‰์ˆœ์„œ๋Š” ์†Œ์Šค์ฝ”๋“œ๊ฐ€ ๋‚˜์—ด๋œ ์ˆœ์„œ์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

  • wait() : ์–ด๋–ค ๊ฐ์ฒด์— ๋Œ€ํ•ด ์“ฐ๋ ˆ๋“œ๋ฅผ ๋Œ€๊ธฐํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.
  • notify() : ๊ฐ์ฒด์— ๋Œ€ํ•ด ๋Œ€๊ธฐ์ค‘์ธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ์“ฐ๋ ˆ๋“œ ํ•˜๋‚˜๋งŒ์„ ๊นจ์šด๋‹ค.
  • notifyAll() : ๋Œ€๊ธฐ์ค‘์ธ ์“ฐ๋ ˆ๋“œ ๋ชจ๋‘ ๊นจ์šด๋‹ค.

wait์™€ notifyAll(notify) ๋ฉ”์„œ๋“œ๋Š” ๋™๊ธฐํ™” ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์„œ, ํ•œ ์ˆœ๊ฐ„์— ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ๋งŒ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ด์•ผํ•œ๋‹ค.

wait๋ฉ”์„œ๋“œ๋Š” ์—ฐ์ด์€ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. = ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ์— ์˜ํ•ด ๋˜ ๋‹ค์‹œ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์ง€๊ธˆ์€ wait์™€ notify๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ด์œ ๊ฐ€ ๋งŽ์ด ์ค„์—ˆ๋‹ค.

  • ์ž๋ฐ” 5์—์„œ ๋„์ž…๋œ ๊ณ ์ˆ˜์ค€์˜ ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ์ด์ „์ด๋ผ๋ฉด wait์™€ notify๋กœ ํ•˜๋“œ์ฝ”๋”ฉํ•ด์•ผ ํ–ˆ๋˜ ์ „ํ˜•์ ์ธ ์ผ๋“ค์„ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • wait์™€ notify๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์•„์ฃผ ๊นŒ๋‹ค๋กœ์šฐ๋‹ˆ ๊ณ ์ˆ˜์ค€ ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ž.

java.util.concurrent์˜ ๊ณ ์ˆ˜์ค€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ์„ธ ๋ฒ”์ฃผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

๋ฐ”๋กœ Excutor framework, ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜, ๋™๊ธฐํ™” ์žฅ์น˜(synchronizer)๋‹ค.

  • ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜์€ List, Queue, Map ๊ฐ™์€ ํ‘œ์ค€ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์— ๋™์‹œ์„ฑ์„ ๊ฐ€๋ฏธํ•ด ๊ตฌํ˜„ํ•œ ๊ณ ์„ฑ๋Šฅ ์ปฌ๋ ‰์…˜์ด๋‹ค. ๋†’์€ ๋™์‹œ์„ฑ์— ๋„๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ๋™๊ธฐํ™”๋ฅผ ๊ฐ์ž์˜ ๋‚ด๋ถ€์—์„œ ์ˆ˜ํ–‰ํ•œ๋‹ค. (์•„์ดํ…œ 79).
  • ๋”ฐ๋ผ์„œ ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜์—์„œ ๋™์‹œ์„ฑ์„ ๋ฌด๋ ฅํ™”ํ•˜๋Š” ๊ฑด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉฐ ์™ธ๋ถ€์—์„œ ๋ฝ์„ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ์†๋„๊ฐ€ ๋Š๋ ค์ง„๋‹ค.
  • ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜์—์„œ ๋™์‹œ์„ฑ์„ ๋ฌด๋ ฅํ™”ํ•˜์ง€ ๋ชปํ•˜๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์›์ž์ ์œผ๋กœ ๋ฌถ์–ด ํ˜ธ์ถœํ•˜๋Š” ์ผ ์—ญ์‹œ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ทธ๋ž˜์„œ ์—ฌ๋Ÿฌ ๊ธฐ๋ณธ ๋™์ž‘์„ ํ•˜๋‚˜์˜ ์›์ž์  ๋™์ž‘์œผ๋กœ ๋ฌถ๋Š” ์ƒํƒœ ์˜์กด์  ์ˆ˜์ • ๋ฉ”์„œ๋“œ๋“ค์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋“ค์€ ์•„์ฃผ ์œ ์šฉํ•ด์„œ ์ž๋ฐ” 8์—์„œ๋Š” ์ผ๋ฐ˜ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์—๋„ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ(์•„์ดํ…œ 21) ํ˜•ํƒœ๋กœ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

  • ์˜ˆ๋ฅผ ๋“ค์–ด Map์˜ putIfAbset(key, value) ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์–ด์ง„ ํ‚ค์— ๋งคํ•‘๋œ ๊ฐ’์ด ์•„์ง ์—†์„ ๋•Œ๋งŒ ์ƒˆ ๊ฐ’์„ ์ง‘์–ด๋„ฃ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด ๊ฐ’์ด ์žˆ์—ˆ๋‹ค๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์—†์—ˆ๋‹ค๋ฉด null์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ ๋•์— ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ ์ •๊ทœํ™” ๋งต(canonicalizing map)์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
// ConcurrentMap์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋™์‹œ์„ฑ ์ •๊ทœํ™” ๋งต
public class Intern {
    // ์ฝ”๋“œ 81-1 ConcurrentMap์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋™์‹œ์„ฑ ์ •๊ทœํ™” ๋งต - ์ตœ์ ์€ ์•„๋‹ˆ๋‹ค. (432์ชฝ)
    private static final ConcurrentMap<String, String> map = new ConcurrentHashMap<>();

    public static String intern(String s) {
        String previousValue = map.putIfAbsent(s, s);
               return previousValue == null ? s : previousValue;
    }
}
  • CuncurrentHashMap์€ get ๊ฐ™์€ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์— ์ตœ์ ํ™” ๋˜์—ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ get์„ ๋จผ์ € ํ˜ธ์ถœํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋งŒ putIfAbsent๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋” ๋น ๋ฅด๋‹ค.
public class Intern {
     private static final ConcurrentMap<String, String> map = new ConcurrentHashMap<>();

    // ์ฝ”๋“œ 81-2 ConcurrentMap์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋™์‹œ์„ฑ ์ •๊ทœํ™” ๋งต - ๋” ๋น ๋ฅด๋‹ค! (432์ชฝ)
    public static String intern(String s) {
        String result = map.get(s);        
        if (result == null) {
            result = map.putIfAbsent(s, s);
            if (result == null)
                result = s;
        }
        return result;
    }
}
  • CuncurrentHashMap์€ ๋™์‹œ์„ฑ์ด ๋›ฐ์–ด๋‚˜๋ฉฐ ์†๋„๋„ ๋ฌด์ฒ™ ๋น ๋ฅด๋‹ค. String.intern๋ณด๋‹ค 6๋ฐฐ๋‚˜ ๋น ๋ฅด๋‹ค.
  • ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜์€ ๋™๊ธฐํ™”ํ•œ ์ปฌ๋ ‰์…˜์„ ๋‚ก์€ ์œ ์‚ฐ์œผ๋กœ ๋งŒ๋“ค์–ด๋ฒ„๋ ธ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋กœ ์ด์ œ๋Š” Collections.synchronizedMap ๋ณด๋‹ค๋Š” ConcurrentHashMap์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ํ›จ์”ฌ ์ข‹๋‹ค.
  • ๋™๊ธฐํ™”๋œ ๋งต์„ ๋™์‹œ์„ฑ ๋งต์œผ๋กœ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋™์‹œ์„ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์€ ๊ทน์ ์œผ๋กœ ๊ฐœ์„ ๋œ๋‹ค.
  • ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์ค‘ ์ผ๋ถ€๋Š” ์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก (์ฆ‰, ์ฐจ๋‹จ๋˜๋„๋ก) ํ™•์žฅ๋˜์—ˆ๋‹ค.
  1. Queue๋ฅผ ํ™•์žฅํ•œ BlockingQueue์— ์ถ”๊ฐ€๋œ ๋ฉ”์„œ๋“œ ์ค‘ take๋Š” ํ์˜ ์ฒซ ์›์†Œ๋ฅผ ๊บผ๋‚ธ๋‹ค.
  2. ์ด๋•Œ ๋งŒ์•ฝ ํ๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์›์†Œ๊ฐ€ ์ถ”๊ฐ€๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค. ์ด๋Ÿฐ ํŠน์„ฑ ๋•์— BlockingQueue๋Š” ์ž‘์—… ํ(์ƒ์‚ฐ์ž-์†Œ๋น„์ž ํ)๋กœ ์“ฐ๊ธฐ์— ์ ํ•ฉํ•˜๋‹ค.
  3. ์ž‘์—… ํ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์ƒ์‚ฐ์ž(producer) ์Šค๋ ˆ๋“œ๊ฐ€ ์ž‘์—…(work)์„ ํ์— ์ถ”๊ฐ€ํ•˜๊ณ , ํ•˜๋‚˜ ์ด์ƒ์˜ ์†Œ๋น„์ž(consumer) ์Šค๋ ˆ๋“œ๊ฐ€ ํ์— ์žˆ๋Š” ์ž‘์—…์„ ๊บผ๋‚ด ์ฒ˜๋ฆฌํ•˜๋Š” ํ˜•ํƒœ๋‹ค.

ThreadPoolExecutor๋ฅผ ํฌํ•จํ•œ ๋Œ€๋ถ€๋ถ„์˜ Excutor Service ๊ตฌํ˜„์ฒด์—์„œ BlockingQueue๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋™๊ธฐํ™” ์žฅ์น˜๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋ฅผ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๊ฒŒํ•˜์—ฌ, ์„œ๋กœ ์ž‘์—…์„ ์กฐ์œจํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

  • ๊ฐ€์žฅ ์ž์ฃผ ์“ฐ์ด๋Š” CountDownLatch์™€ Semaphore
  • CyclicBarrier ์™€ Exchanger๋Š” ๊ทธ๋ณด๋‹ค ๋œ ์“ฐ์ธ๋‹ค.
  • ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ๋™๊ธฐํ™” ์žฅ์น˜๋Š” Phaser๋‹ค.
  • ์นด์šดํŠธ๋‹ค์šด ๋ž˜์น˜๋Š” ์ผํšŒ์„ฑ ์žฅ๋ฒฝ์œผ๋กœ ํ•˜๋‚˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋˜ ๋‹ค๋ฅธ ํ•˜๋‚˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ ์ž‘์—…์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•œ๋‹ค.
  • CountDownLatch์˜ ์œ ์ผํ•œ ์ƒ์„ฑ์ž๋Š” int ๊ฐ’์„ ๋ฐ›์œผ๋ฉฐ, ์ด ๊ฐ’์ด ๋ž˜์น˜์˜ countDown ๋ฉ”์„œ๋“œ๋ฅผ ๋ช‡๋ฒˆ ํ˜ธ์ถœํ•ด์•ผ ๋Œ€๊ธฐ์ค‘์ธ ์Šค๋ ˆ๋“œ๋“ค์„ ๊นจ์šฐ๋Š”์ง€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.

์–ด๋–ค ๋™์ž‘๋“ค์„ ๋™์‹œ์— ์‹œ์ž‘ํ•ด ๋ชจ๋‘ ์™„๋ฃŒํ•˜๊ธฐ๊นŒ์ง€์˜ ์‹œ๊ฐ„์„ ์žฌ๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž.

  • ์นด์šดํŠธ๋‹ค์šด ๋ž˜์น˜ 3๊ฐœ ์‚ฌ์šฉ
  1. ready Latch : ์ž‘์—…์ž ์Šค๋ ˆ๋“œ๋“ค์ด ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Œ์„ ํƒ€์ด๋จธ ์Šค๋ ˆ๋“œ์— ํ†ต์ง€ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
  1. ํ†ต์ง€๋ฅผ ๋๋‚ธ ์ž‘์—…์ž ์Šค๋ ˆ๋“œ๋“ค์€ ๋‘ ๋ฒˆ์งธ ๋ž˜์น˜์ธ start๊ฐ€ ์—ด๋ฆฌ๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
  1. ๋งˆ์ง€๋ง‰ ์ž‘์—…์ž ์Šค๋ ˆ๋“œ๊ฐ€ ready.countDown์„ ํ˜ธ์ถœํ•˜๋ฉด ํƒ€์ด๋จธ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹œ์ž‘ ์‹œ๊ฐ์„ ๊ธฐ๋กํ•˜๊ณ  start.countDown์„ ํ˜ธ์ถœํ•˜๋ฉด ํƒ€์ด๋จธ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹œ์ž‘ ์‹œ๊ฐ์„ ๊ธฐ๋กํ•˜๊ณ  start.countDown์„ ํ˜ธ์ถœํ•˜์—ฌ ๊ธฐ๋‹ค๋ฆฌ๋˜ ์ž‘์—…์ž ์Šค๋ ˆ๋“œ๋“ค์„ ๊นจ์šด๋‹ค.
  1. ๊ทธ ์งํ›„ ํƒ€์ด๋จธ ์Šค๋ ˆ๋“œ๋Š” ์„ธ๋ฒˆ์งธ ๋ž˜์น˜์ธ done์ด ์—ด๋ฆฌ๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
  1. done ๋ž˜์น˜๋Š” ๋งˆ์ง€๋ง‰ ๋‚จ์€ ์ž‘์—…์ž ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์ž‘์„ ๋งˆ์น˜๊ณ  done.countDown์„ ํ˜ธ์ถœํ•˜๋ฉด ์—ด๋ฆฐ๋‹ค.
  1. ํƒ€์ด๋จธ ์Šค๋ ˆ๋“œ๋Š” done ๋ž˜์น˜๊ฐ€ ์—ด๋ฆฌ์ž๋งˆ์ž ๊นจ์–ด๋‚˜ ์ข…๋ฃŒ ์‹œ๊ฐ์„ ๊ธฐ๋กํ•œ๋‹ค.
// ์ฝ”๋“œ 81-3 ๋™์‹œ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์žฌ๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋ ˆ์ž„์›Œํฌ (433-434์ชฝ)
public class ConcurrentTimer {
     //์ด ๋™์ž‘์„ ์‹คํ–‰ํ•  excutor์™€ ๋ช‡ ๊ฐœ๋‚˜ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋œปํ•˜๋Š” ๋™์‹œ์„ฑ ์ˆ˜์ค€ ๋“ฑ) 
    public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {
        CountDownLatch ready = new CountDownLatch(concurrency);  
        CountDownLatch start = new CountDownLatch(1);
        CountDownLatch done  = new CountDownLatch(concurrency);

        for (int i = 0; i < concurrency; i++) {
            executor.execute(() -> {
                ready.countDown(); // ํƒ€์ด๋จธ์—๊ฒŒ ์ค€๋น„๋ฅผ ๋งˆ์ณค์Œ์„ ์•Œ๋ฆฐ๋‹ค.
                try {
                    start.await(); // ๋ชจ๋“  ์ž‘์—…์ž ์Šค๋ ˆ๋“œ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
                    action.run();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    done.countDown();  // ํƒ€์ด๋จธ์—๊ฒŒ ์ž‘์—…์„ ๋งˆ์ณค์Œ์„ ์•Œ๋ฆฐ๋‹ค.
                }
            });
        }

        ready.await();     // ๋ชจ๋“  ์ž‘์—…์ž๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
        long startNanos = System.nanoTime();
        start.countDown(); // ์ž‘์—…์ž๋“ค์„ ๊นจ์šด๋‹ค.
        done.await();      // ๋ชจ๋“  ์ž‘์—…์ž๊ฐ€ ์ผ์„ ๋๋งˆ์น˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
        return System.nanoTime() - startNanos;
    }
}

ํ•ต์‹ฌ ์ •๋ฆฌ

  • ์ƒˆ๋กœ์šด ์ฝ”๋“œ๋ผ๋ฉด ์–ธ์ œ๋‚˜ wait์™€ notify๊ฐ€ ์•„๋‹Œ ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์จ์•ผํ•œ๋‹ค.

  • wait ๋ฉ”์„œ๋“œ๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ์–ด๋–ค ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

  • ๋ฝ ๊ฐ์ฒด์ธ wait ๋ฉ”์„œ๋“œ๋Š” ๋ฐ˜๋“œ์‹œ ๊ทธ ๊ฐ์ฒด๋ฅผ ์ž ๋“  ๋™๊ธฐํ™” ์˜์—ญ ์•ˆ์—์„œ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

  • wait์™€ notify๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋™์‹œ์„ฑ '์–ด์…ˆ๋ธ”๋ฆฌ ์–ธ์–ด'๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๋Š” ๊ฒƒ์— ๋น„์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ฐ˜๋ฉด java.util.concurrent๋Š” ๊ณ ์ˆ˜์ค€ ์–ธ์–ด์— ๋น„์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ฝ”๋“œ๋ฅผ ์ƒˆ๋กœ ์ž‘์„ฑํ•œ๋‹ค๋ฉด wait์™€ notify๋ฅผ ์“ธ ์ด์œ ๊ฐ€ ๊ฑฐ์˜(์–ด์ฉŒ๋ฉด ์ „ํ˜€) ์—†๋‹ค.

  • wait๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ๋ฅผ ์œ ์ง€๋ณด์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค๋ฉด wait๋Š” ํ•ญ์ƒ ํ‘œ์ค€ ๊ด€์šฉ๊ตฌ์— ๋”ฐ๋ผ while๋ฌธ ์•ˆ์—์„œ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜์ž.