μ§κΈμ waitμ notifyλ₯Ό μ¬μ©ν΄μΌ ν μ΄μ κ° λ§μ΄ μ€μλ€. μλ° 5μμ λμ λ κ³ μμ€μ λμμ± μ νΈλ¦¬ν°κ° μ΄μ μ΄λΌλ©΄ waitμ notifyλ‘ νλμ½λ©ν΄μΌ νλ μ νμ μΈ μΌλ€μ λμ μ²λ¦¬ν΄μ£ΌκΈ° λλ¬Έμ΄λ€. waitμ notifiyλ μ¬λ°λ₯΄κ² μ¬μ©νκΈ°κ° μμ£Ό κΉλ€λ‘μ°λ κ³ μμ€ λμμ± μ νΈλ¦¬ν°λ₯Ό μ¬μ©νμ.
java.util.concurrent
ν¨ν€μ§λ κ³ μμ€μ λμμ± μ νΈλ¦¬ν°λ₯Ό μ 곡νλ€. μ΄ ν¨ν€μ§λ ν¬κ² μΈ κ°μ§ μ£Όμ λ²μ£Όλ‘ λλ μ μλ€:
- μ€νμ νλ μμν¬ (Executor Framework)
- λμμ± μ»¬λ μ (Concurrent Collections)
- λκΈ°ν μ₯μΉ (Synchronizers)
κ°κ°μ κΈ°λ₯κ³Ό λμ λ°©μμ μμΈν μ΄ν΄λ³΄μ.
λμμ± μ»¬λ μ
μ List
, Queue
, Map
κ³Ό κ°μ νμ€ μ»¬λ μ
μΈν°νμ΄μ€μ λμμ± κΈ°λ₯μ μΆκ°ν 컬λ μ
μ΄λ€.
- λ΄λΆμ μΌλ‘ λκΈ°νλ₯Ό μννλ©°, μΈλΆμμ λ³λλ‘ λ½μ κ±Έμ΄ λκΈ°νλ₯Ό μλνλ©΄ μ€νλ € μ±λ₯μ΄ μ νλλ€. μ¦, λμμ± μ»¬λ μ μμ λμμ±μ 무λ ₯ννλ 건 λΆκ°λ₯νλ©° , μΈλΆμμ λ½μ μΆκ°λ‘ μ¬μ©νλ©΄ μ€νλ € μλκ° λλ € μ§λ€
- μ¬λ¬ λ©μλλ₯Ό μμμ μΌλ‘ λ¬Άμ΄ νΈμΆνλ μΌ μμ λΆκ°λ₯νλ€.
- λκΈ°νλ 컬λ μ λμ λμμ± μ»¬λ μ μ μ¬μ©νλ κ²μ΄ λ ν¨μ¨μ μ΄λ€.
λμμ± μ»¬λ μ μ μμμ μΌλ‘ μ¬λ¬ λ©μλλ₯Ό νΈμΆνλ κ²μ΄ λΆκ°λ₯νλ€. μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μ¬λ¬ λμμ νλμ μμμ λμμΌλ‘ λ¬Άλ μν μμ‘΄μ λ©μλκ° μΆκ°λμλ€.
putIfAbsent
λ©μλ μμ
μ΄ λ©μλ λμ μ€λ λ μμ ν μ κ·ν 맡 (canonicalizing map)μ μ½κ² ꡬνν μ μλ€.
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;
}
μ€λͺ
map.putIfAbsent(s, s)
s
λΌλ ν€κ° μ‘΄μ¬νμ§ μμΌλ©΄s
λ₯Ό 맡μ μΆκ°νκ³null
μ λ°νs
λΌλ ν€κ° μ΄λ―Έ μ‘΄μ¬νλ©΄ κΈ°μ‘΄ κ°μ λ°ν
return
λ¬ΈpreviousValue
κ°null
μΈ κ²½μ° β μ λ ₯λ λ¬Έμμ΄s
λ₯Ό λ°ν.previousValue
κ°null
μ΄ μλ κ²½μ° β μ΄λ―Έ μ‘΄μ¬νλ κ°μ λ°ν.
μμ§ κ°μ ν κ² λ¨μλ€. ConcurrentHashMapμ get κ°μ κ²μ κΈ°λ₯μ μ΅μ νλμλ€. λ°λΌμ getμ λ¨Όμ νΈμΆνμ¬ νμν λλ§ putlfAbsentλ₯Ό νΈμΆνλ©΄ λ λΉ λ₯΄λ€.
putIfAbsent
λ ConcurrentMap
μ μΆκ°λ λ©μλλ‘, ν€κ° μμ λλ§ κ°μ μΆκ°νλ λμμ μννλ€. κΈ°μ‘΄ κ°μ΄ μμΌλ©΄ κ·Έ κ°μ λ°ννκ³ , μμΌλ©΄ null
μ λ°ννλ€.
μλλ String.intern
λ©μλλ₯Ό ConcurrentHashMap
μΌλ‘ νλ΄ λΈ μμ μ½λλ€:
// ConcurrentHashMapμ μ¬μ©ν΄ λ¬Έμμ΄μ μ κ·ννλ λ©μλ
private static final ConcurrentMap<String, String> map = new ConcurrentHashMap<>();
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;
}
μ½λ μ€λͺ :
get
: λ¨Όμ ν€μ ν΄λΉνλ κ°μ νμΈνλ€.putIfAbsent
: ν€κ° μμΌλ©΄ κ°μ μΆκ°νλ©°, μμμ μΌλ‘ μ€νλλ€.- κ²°κ³Ό: μ€λ λ μμ ν μ κ·ν 맡μ ꡬνν μ μλ€.
Tip:
ConcurrentHashMap
μ κ²μ κΈ°λ₯μ μ΅μ νλμ΄ μμΌλ―λ‘, λ¨Όμ get
μ νΈμΆνλ©΄ μ±λ₯μ΄ λμ± ν₯μλλ€.
μ λμμ± μ»¬λ μ μ΄ μ€μνκ°?
- ConcurrentHashMapμ λμμ±μ΄ λ°μ΄λλ©° μλλ λ¬΄μ² λΉ λ₯΄λ€.
- λ΄ μ»΄ν¨ν°μμ μ΄ λ©μλλ String, intern λ³΄λ€ 6λ°°λ λΉ λ₯΄λ€(νμ§λ§ String, intern μλ μ€λ μ€ν λλ νλ‘κ·Έλ¨ μμ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§νλ κΈ°μ λ λ€μ΄κ° μμμ κ°μνμ)
Collections.synchronizedMap
λμConcurrentHashMap
μ μ¬μ©νλ©΄ μ±λ₯μ΄ ν¬κ² κ°μ λλ€.- λκΈ°νλ 맡μ λμμ± λ§΅μΌλ‘ κ΅μ²΄νλ κ²λ§μΌλ‘ λμμ± μ ν리μΌμ΄μ μ μ±λ₯μ κ·Ήμ μΌλ‘ κ°μ λλ€.
- λ΄λΆ λκΈ°νλ₯Ό ν΅ν΄ λμ λμμ±μ μ 곡νλ©°, μΈλΆμμ μΆκ°μ μΈ λκΈ°νκ° νμνμ§ μλ€.
컬λ μ μΈν°νμ΄μ€
μ€ μΌλΆλ μμ μ΄ μ±κ³΅μ μΌλ‘ μλ£λ λκΉμ§ κΈ°λ€λ¦¬λλ‘ (μ¦, μ°¨λ¨λλλ‘) νμ₯λμλ€.
1. BlockingQueue
μ μ:
BlockingQueue
λ νμ νμ₯μΌλ‘, λΉμ΄μκ±°λ κ°λ μ°¬ μνμ λ°λΌ μμ
μ΄ μ°¨λ¨λλλ‘ μ§μνλ€.
- μμ°μ-μλΉμ ν¨ν΄μ λ§€μ° μ μ©νλ©°, μ€λ λ κ° μμ νκ² λ°μ΄ν°λ₯Ό 곡μ ν μ μλλ‘ μ€κ³λμλ€.
take()
λ©μλλ νκ° λΉμ΄ μμ κ²½μ° μμκ° μΆκ°λ λκΉμ§ κΈ°λ€λ¦°λ€.put()
λ©μλλ νκ° κ°λ μ°Όμ κ²½μ° κ³΅κ°μ΄ μκΈΈ λκΉμ§ κΈ°λ€λ¦°λ€.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerExample {
private static final int CAPACITY = 5; // ν μ©λ μ€μ
private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(CAPACITY);
public static void main(String[] args) {
// μμ°μ μ€λ λ
Thread producer = new Thread(() -> {
try {
for (int i = 1; i <= 10; i++) {
System.out.println("μμ°μ: " + i + " μΆκ°");
queue.put(i); // νμ μμλ₯Ό μΆκ° (κ°λ μ°¨λ©΄ λκΈ°)
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// μλΉμ μ€λ λ
Thread consumer = new Thread(() -> {
try {
while (true) {
Integer value = queue.take(); // νμμ μμλ₯Ό κΊΌλ (λΉμ΄μμΌλ©΄ λκΈ°)
System.out.println("μλΉμ: " + value + " μ²λ¦¬");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
}
}
2. CountDownLatch
μ μ:
CountDownLatch
λ μΌνμ± λκΈ°ν μ₯μΉλ‘, μ§μ λ μμ
μ΄ μλ£λ λκΉμ§ λ€λ₯Έ μ€λ λμ μ€νμ μ°¨λ¨νλ€.
countDown()
: νΈμΆλ λλ§λ€ μΉ΄μ΄νΈκ° κ°μνλ€.await()
: μΉ΄μ΄νΈκ°0
μ΄ λ λκΉμ§ νμ¬ μ€λ λλ₯Ό μ°¨λ¨νλ€.
CountDownLatchλ μΌνμ± μ₯λ²½μΌλ‘, νλ μ΄μμ μ€λ λκ° λ λ€λ₯Έ νλ μ΄μμ μ€λ λ μμ μ΄ λλ λκΉμ§ κΈ°λ€λ¦¬κ² νλ μν μ νλ€.
μμ±μλ‘ λ°λ int κ°μ λ°μΌλ©°, μ΄ κ°μ΄ countDown λ©μλλ₯Ό λͺ λ² νΈμΆν΄μΌ λκΈ° μ€μΈ μ€λ λλ₯Ό κΉ¨μ°λμ§λ₯Ό κ²°μ νλ€.
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) {
int numberOfWorkers = 3;
CountDownLatch latch = new CountDownLatch(numberOfWorkers);
// μμ
μ μ€λ λ
for (int i = 1; i <= numberOfWorkers; i++) {
new Thread(new Worker(latch, i)).start();
}
try {
latch.await(); // λͺ¨λ μμ
μ μ€λ λμ μμ
μ΄ λλ λκΉμ§ λκΈ°
System.out.println("λͺ¨λ μμ
μλ£. λ©μΈ μ€λ λ μ§ν.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
static class Worker implements Runnable {
private final CountDownLatch latch;
private final int workerId;
Worker(CountDownLatch latch, int workerId) {
this.latch = latch;
this.workerId = workerId;
}
@Override
public void run() {
System.out.println("μμ
μ " + workerId + " μμ
μμ");
try {
Thread.sleep(1000 * workerId); // κ° μ€λ λκ° λ€λ₯Έ μκ°μ μ’
λ£λλλ‘ μ€μ
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("μμ
μ " + workerId + " μμ
μλ£");
latch.countDown(); // μΉ΄μ΄νΈ λ€μ΄
}
}
}
π μ 리
- νΉμ§: νκ° λΉμ΄μκ±°λ κ°λ μ°¨λ©΄ μμ μ΄ μ°¨λ¨λ¨.
- μ¬μ© μ¬λ‘:
- μμ°μ-μλΉμ ν¨ν΄
- μμ ν (ThreadPoolExecutor λ΄λΆμμ μ¬μ©λ¨)
- νΉμ§: μ§μ λ κ°μλ§νΌ
countDown()
μ΄ νΈμΆλ λκΉμ§ λ€λ₯Έ μ€λ λμ μμ μ μ°¨λ¨ν¨. - μ¬μ© μ¬λ‘:
- λ€μμ μμ μ λ³λ ¬λ‘ μ²λ¦¬ν ν νλμ μμ μ μμν λ
- νΉμ μ€λ λλ€μ΄ λͺ¨λ μλ£λ λκΉμ§ λκΈ°ν λ
λκΈ°ν μ₯μΉλ μ¬λ¬ μ€λ λ κ°μ μμ μ μ‘°μ¨νκ±°λ νλ ₯ν μ μλλ‘ λμμ£Όλ λꡬμ΄λ€. λνμ μΈ λκΈ°ν μ₯μΉλ λ€μκ³Ό κ°λ€:
- CountDownLatch: μ¬λ¬ μ€λ λμ μμ μ΄ λλ λκΉμ§ λκΈ°.
- Semaphore: μ§μ λ μμ μ€λ λλ§ λμμ μ κ·Όν μ μλλ‘ μ ν.
- CyclicBarrier: μ¬λ¬ μ€λ λκ° λμμ λ§λλλ‘ μ‘°μ¨.
- Exchanger: λ μ€λ λ κ° λ°μ΄ν°λ₯Ό κ΅ν.
- Phaser: λ€μ€ λ¨κ³ μμ μ‘°μ¨μ μ¬μ©λλ κ°λ ₯ν λκΈ°ν μ₯μΉ.
CountDownLatchλ μΌνμ± λκΈ°ν μ₯μΉλ‘, μ ν΄μ§ νμλ§νΌ countDown()
μ΄ νΈμΆλ λκΉμ§ μ€λ λκ° λκΈ°νλ€. μ¦, νλ μ΄μμ μ€λ λκ° λ λ€λ₯Έ νλ μ΄μμ μ€λ λ μμ
μ΄ λλ λκΉμ§ κΈ°λ€λ¦¬κ² νλ€.
λμ μ€ν μκ° μΈ‘μ μμ
μ΄ νλ μμν¬λ λ©μλ νλλ‘ κ΅¬μ±λλ©°, μ΄ λ©μλλ λμλ€μ μ€νν μ€νμμ λμμ λͺ κ°λ λμμ μν ν μ μλμ§λ₯Ό λ»νλ λμμ± μμ€(concurrency)μ 맀κ°λ³μλ‘ λ°λλ€.
νμ΄λ¨Έ μ€λ λκ° μκ³λ₯Ό μμνκΈ° μ μ λͺ¨λ μμ μ μ€λ λλ λμμ μνν μ€λΉ λ₯Ό λ§μΉλ€. λ§μ§λ§ μμ μ μ€λ λκ° μ€λΉλ₯Ό λ§μΉλ©΄ νμ΄λ¨Έ μ€λ λκ° βμμ λ°©μμ βλ₯Ό λΉκ²¨ μμ μ μ€λ λλ€μ΄ μΌμ μμνκ² νλ€. λ§μ§λ§ μμ μ μ€λ λκ° λμμ λ§μΉμλ§μ νμ΄λ¨Έ μ€λ λλ μκ³λ₯Ό λ©μΆλ€. μ΄μμ κΈ°λ₯μ wait μ notifyλ§μΌλ‘ ꡬννλ €λ©΄ μμ£Ό λν΄νκ³ μ§μ λΆν μ½λκ° νμνμ§λ§,
CountDownLatch
λ₯Ό μ°λ©΄ λλλλ‘ μ§κ΄μ μΌλ‘ ꡬνν μ μλ€.
μλλ μ¬λ¬ μμ μμ μ€λΉ λ° λμ μ€ν μκ°μ μΈ‘μ νλ μ½λμ΄λ€:
import java.util.concurrent.*;
public class CountDownLatchTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
try {
long result = time(executorService, 3, () -> System.out.println("Hello"));
System.out.println("Execution time: " + result + " nanoseconds");
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
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;
}
}
μ½λ μ€λͺ :
ready
: μμ μλ€μ΄ μ€λΉλμμμ μλ¦Ό.start
: λͺ¨λ μμ μμκ² μμ μμ μ νΈλ₯Ό 보λ.done
: μμ μλ£ μλ¦Ό.- κ²°κ³Ό: μ¬λ¬ μ€λ λλ₯Ό λμμ μμνκ³ μλ£ μκ°μ μ νν μΈ‘μ νλ€.
μκ° κ°κ²©μ μ΄ λλ νμ System.currentTiune1Vlillisκ° μλ System.nanoTime μ μ¬μ©νμ. System.nanoTimeμ λ μ ννκ³ μ λ°νλ©° μμ€ν μ μ€μκ° μκ³ μ μκ° λ³΄μ μ μν₯λ°μ§ μλλ€.
λΆκ° μ€λͺ
CountDownLatch
λ₯Ό 3κ° μ¬μ©νμ¬ νμ΄λ¨Έ μ€λ λμ μμ
μ μ€λ λ κ°μ λκΈ°νλ₯Ό κ΄λ¦¬νλ€.
- ready λμΉ: μμ μ μ€λ λκ° μ€λΉκ° μλ£λμμμ νμ΄λ¨Έ μ€λ λμ μλ¦Ό.
- start λμΉ: νμ΄λ¨Έ μ€λ λκ° λͺ¨λ μμ μ μ€λ λμ μ€λΉλ₯Ό νμΈν ν, μμ μμμ μλ¦Ό.
- done λμΉ: μμ μ μ€λ λκ° μμ μ μλ£νμμ νμ΄λ¨Έ μ€λ λμ μλ¦Ό.
μ€λ λμ μ€λΉ β μμ μμ β μμ μλ£ κ³Όμ μ μ νν μμ μ λ§μΆμ΄ λκΈ°ν
1. λκΈ° λ°λ³΅λ¬Έ(wait loop) κ΄μ©κ΅¬λ₯Ό μ¬μ©νλΌ
- λ°λ³΅λ¬Έ μμμ
wait()
λ₯Ό νΈμΆν΄μΌ νλ€. - λκΈ° μ : μ‘°κ±΄μ΄ μ΄λ―Έ μΆ©μ‘±λμλ€λ©΄
wait()
λ₯Ό 건λλ΄λ€ β μλ΅ λΆκ° μν μλ°© - λκΈ° ν: μ‘°κ±΄μ΄ μΆ©μ‘±λμ§ μμμΌλ©΄ λ€μ
wait()
λ‘ λμκ°λ€ β μμ μ€ν¨ λ°©μ§
λ°λ³΅λ¬Έ λ°μμ μ λ
wait()
λ₯Ό νΈμΆνμ§ λ§λΌ.
μλ‘μ΄ μ½λμμλ wait
μ notify
λμ λμμ± μ νΈλ¦¬ν°λ₯Ό μ¬μ©νλ κ²μ΄ μ’λ€. νμ§λ§ λ κ±°μ μ½λμμ μ¬μ©ν μλ°μ μλ€λ©΄ λ€μκ³Ό κ°μ΄ μ¬μ©ν΄μΌ νλ€:
synchronized (obj) {
while (μ‘°κ±΄μ΄ μΆ©μ‘±λμ§ μμλ€) {
obj.wait(); // νμ¬ μ€λ λλ₯Ό λκΈ° μνλ‘ μ ν
}
// μ‘°κ±΄μ΄ μΆ©μ‘±λμμ λ μνν λμ
}
2. μ‘°κ±΄μ΄ μΆ©μ‘±λμ§ μμλ κΉ¨μ΄λ μ μλ μν©λ€
- λ€λ₯Έ μ€λ λμ μν λ³κ²½
notify()
νΈμΆ ν λ€λ₯Έ μ€λ λκ° λ½μ μ»μ΄ μνλ₯Ό λ³κ²½ν μ μλ€.
- μ€μ λλ μ
μμ
notify
νΈμΆ- μΈλΆμ λ
ΈμΆλ κ°μ²΄λ₯Ό λ½μΌλ‘ μ¬μ©νλ©΄ λ€λ₯Έ μ€λ λκ°
notify
λ₯Ό μ€μλ‘ νΈμΆν μ μλ€.
- μΈλΆμ λ
ΈμΆλ κ°μ²΄λ₯Ό λ½μΌλ‘ μ¬μ©νλ©΄ λ€λ₯Έ μ€λ λκ°
- νμ κ°μ±(Spurious Wakeup)
notify
κ° νΈμΆλμ§ μμλλ°λ μ€λ λκ° κΉ¨μ΄λλ νμ. μ΄λ λλ¬Όμ§λ§ λ°μν μ μλ€. μ€λ λκ°notify
μμ΄λ κΉ¨μ΄λλ νμμ νμ κ°μ±μ΄λΌκ³ νλ€. μ΄λ₯Ό λ°©μ§νλ €λ©΄wait
λ₯Ό λ°λμ λ°λ³΅λ¬Έ λ΄λΆμμ νΈμΆν΄μΌ νλ€.
- κ³Όλν
notifyAll
νΈμΆ- μ‘°κ±΄μ΄ μΆ©μ‘±λμ§ μμ μ€λ λκΉμ§ λͺ¨λ κΉ¨μ΄λ μ μλ€.
- νμ§λ§ κΉ¨μ΄λ μ€λ λκ° μ‘°κ±΄μ κ²μ¬νκ³ μΆ©μ‘±λμ§ μμΌλ©΄ λ€μ λκΈ°νκ² λλ―λ‘ νλ‘κ·Έλ¨μ μ νμ±μ μ μ§λλ€.
3. notifyμ notifyAll μ€ λ¬΄μμ μ¬μ©ν΄μΌ νλκ°?
- νμ
notifyAll()
μ μ¬μ©νλΌ.- λͺ¨λ λκΈ° μ€μΈ μ€λ λκ° κΉ¨μ΄λ 쑰건μ νμΈνκ² λλ―λ‘ μ νν κ²°κ³Όλ₯Ό 보μ₯νλ€.
- μΌλΆ μ€λ λκ° λΆνμνκ² κΉ¨μ΄λλλΌλ μ΄λ μ±λ₯ λ¬Έμ μΌ λΏ νλ‘κ·Έλ¨μ μ νμ±μ μν₯μ λ―ΈμΉμ§ μλλ€.
- λ¨ νλμ μ€λ λλ§ μ‘°κ±΄μ μΆ©μ‘±ν λ μ΅μ νλ₯Ό μν΄
notify()
λ₯Ό μ¬μ©ν μ μλ€. - νμ§λ§, λ€μκ³Ό κ°μ μνμ΄ μλ€:
- λ€λ₯Έ μ€λ λκ° μ€μλ‘ μ€μν
notify
λ₯Ό μΌμΌλ²λ¦¬λ©΄ νμμ μΌλ‘ κΉ¨μ΄λμΌ ν μ€λ λκ° μμν λκΈ° μνμ λΉ μ§λ€. - μ΄λ μΈλΆμ 곡κ°λ κ°μ²΄μ λν΄ μ
μμ μΌλ‘
wait
λ₯Ό νΈμΆνλ κ²½μ° λμ± μΉλͺ μ μ΄λ€.
- λ€λ₯Έ μ€λ λκ° μ€μλ‘ μ€μν
notify
: λκΈ° μ€μΈ μ€λ λ μ€ νλλ§ κΉ¨μ΄λ€.notifyAll
: λͺ¨λ λκΈ° μ€μΈ μ€λ λλ₯Ό κΉ¨μ΄λ€.
μμ ν μ ν: μΌλ°μ μΌλ‘
notifyAll
μ μ¬μ©νλ κ²μ΄ λ μμ νλ€. μ‘°κ±΄μ΄ λ§μ‘±λμ§ μμ μ€λ λλ€μ λ€μ λκΈ° μνλ‘ λμκ°λ―λ‘ λ¬Έμ κ° μλ€.
wait
μnotify
λ λμμ±μ μ΄μ λΈλ¦¬ μΈμ΄μ λΉμ λλ€.java.util.concurrent
λ κ³ μμ€ μΈμ΄λ‘, λ μμ νκ³ κ°λ ₯ν λμμ± μ νΈλ¦¬ν°λ₯Ό μ 곡νλ€.
- μλ‘μ΄ μ½λμμλ
wait
μnotify
λ₯Ό μ¬μ©ν νμκ° κ±°μ μλ€. - λ κ±°μ μ½λ μ μ§λ³΄μ μ:
wait()
λ λ°λμ while λ¬Έ μμμ νΈμΆνλΌ.notifyAll()
μ μ¬μ©νλΌ.notify
λ κ·Ήν μ‘°μ¬ν΄μ μ¬μ©ν΄μΌ νλ€.
java.util.concurrent
ν¨ν€μ§λ 볡μ‘ν λμμ± λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν κ³ μμ€ μ νΈλ¦¬ν°λ₯Ό μ 곡νλ€.
- λμμ± μ»¬λ μ
:
ConcurrentHashMap
κ³Ό κ°μ 컬λ μ μ λμ λμμ±μ μ 곡νλ©° μΈλΆ λκΈ°νκ° νμ μλ€. - λκΈ°ν μ₯μΉ:
CountDownLatch
,Semaphore
,Phaser
λ±μ ν΅ν΄ μ€λ λ κ° νλ ₯ λ° μμ μ‘°μ¨μ ν μ μλ€. - λ κ±°μ μ½λ:
wait
μnotify
λ₯Ό μ¬μ©ν΄μΌ νλ€λ©΄ λ°λμ λ°λ³΅λ¬Έκ³Ό ν¨κ» μ¬μ©νλ©°notifyAll
μ κΆμ₯νλ€.
μλ‘μ΄ μ½λμμλ λμμ± μ νΈλ¦¬ν°λ₯Ό μ κ·Ή νμ©νμ¬ μμ νκ³ ν¨μ¨μ μΈ λμμ± νλ‘κ·Έλλ°μ ꡬννμ.
μ°Έκ³
- https://jjingho.tistory.com/131