Exchanger — 스레드 간 객체 교환 지점
Exchanger — 스레드 간 객체 교환 지점
Exchanger<V>는 두 스레드가 짝을 지어 객체를 교환(swap) 할 수 있는 동기화 지점이에요. 각 스레드는 exchange 메서드에 진입할 때 어떤 객체를 제시하고, 파트너 스레드와 매칭된 뒤 파트너의 객체를 받아 돌아와요. SynchronousQueue의 양방향(bidirectional) 형태로 볼 수 있어요.
본문
개념 이해하기
Exchanger는 스레드들이 짝을 지어 쌍 내에서 요소를 교환할 수 있는 동기화 지점이에요. 각 스레드는 exchange에 진입할 때 객체를 제시하고, 파트너 스레드와 매칭된 뒤 파트너의 객체를 받아요. 유전 알고리즘이나 파이프라인 설계 같은 애플리케이션에서 유용할 수 있어요.
public class Exchanger<V>
extends Object
활용 예 — 버퍼 교환
버퍼를 채우는 스레드가 필요할 때 갓 비워진 버퍼를 받고, 채운 버퍼를 비우는 스레드에 넘겨주는 구조를 만들 수 있어요.
class FillAndEmpty {
Exchanger<DataBuffer> exchanger = new Exchanger<>();
DataBuffer initialEmptyBuffer = ...; // a made-up type
DataBuffer initialFullBuffer = ...;
class FillingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ...}
}
}
class EmptyingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ...}
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}
메모리 일관성 효과: Exchanger를 통해 객체를 성공적으로 교환하는 각 스레드 쌍에 대해, 각 스레드에서 exchange() 전의 동작은 다른 스레드의 대응하는 exchange() 반환에 뒤따르는 동작보다 happen-before 관계예요.
생성자
public Exchanger() — 새 Exchanger를 만들어요.
교환
public V exchange(V x) throws InterruptedException — 다른 스레드가 이 교환 지점에 도착할 때까지 기다렸다가(현재 스레드가 인터럽트되지 않는 한) 주어진 객체를 전달하고 그 객체를 받아요. 이미 다른 스레드가 기다리고 있으면 즉시 재개되어 객체를 받고, 현재 스레드는 그 다른 스레드가 넘긴 객체를 받아 즉시 반환해요. 기다리는 스레드가 없으면, 어떤 스레드가 교환에 들어오거나 인터럽트될 때까지 대기 상태가 돼요.
- 반환: 다른 스레드가 제공한 객체
InterruptedException— 대기 중 인터럽트(인터럽트 상태는 클리어됨)
public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException — 다른 스레드가 도착하거나 인터럽트되거나 지정 대기 시간이 지날 때까지 기다렸다가 객체를 교환해요. 시간이 지나면 TimeoutException. 시간이 0보다 작거나 같으면 전혀 기다리지 않아요.