μ§κΈμ 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
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png)

 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png)
.png)