Java Exchanger: นัดแลกข้อมูลระหว่างสองงานแบบเจอกันพอดี
งานสองตัวที่ต้องส่งของให้กันตรงจังหวะ เช่น producer ส่ง batch เต็มและรับ buffer ว่างกลับมา ใช้ Exchanger เป็นจุดนัดพบแบบสองฝ่ายได้ครับ ทั้งคู่เรียก exchange แล้วรอจนคู่ของมันมาถึง
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws Exception {
Exchanger<String> exchanger = new Exchanger<>();
ExecutorService pool = Executors.newFixedThreadPool(2);
try {
Future<String> left = pool.submit(
() -> exchanger.exchange("full-batch", 1, TimeUnit.SECONDS));
Future<String> right = pool.submit(
() -> exchanger.exchange("empty-buffer", 1, TimeUnit.SECONDS));
assert left.get().equals("empty-buffer");
assert right.get().equals("full-batch");
} finally {
pool.shutdownNow();
}
}
}
เหมือนคนส่งอาหารสองฝั่งสะพานต้องมาถึงจุดกลางก่อนจึงสลับตะกร้าได้ จุดแข็งคือไม่มี mailbox ค้างอยู่ แต่ถ้าฝ่ายหนึ่งล้ม อีกฝ่ายอาจรอไม่จบ จึงควรใช้ overload ที่มี timeout และกำหนดว่าจะ retry, abort หรือคืน buffer อย่างไร
Exchanger เหมาะกับสอง party ต่อหนึ่งรอบ ถ้ามี producer/consumer หลายตัว ต้อง buffer งาน หรืออยากเลือกคนรับแบบยืดหยุ่น BlockingQueue มักตรงกว่า อย่าใช้เพียงเพราะชื่อดู concurrent ครับ
Recap
- ใช้กับการแลกข้อมูลแบบสองฝ่าย
- ตั้ง timeout แทนการรอไม่สิ้นสุด
- ออกแบบ recovery เมื่อคู่แลกถูกยกเลิก
- ใช้ queue เมื่อ topology มีหลายฝ่ายหรือจำเป็นต้อง buffer