นากแม่น้ำต้นฉบับกำลังส่งกล่องข้ามช่องว่างตรงถึงมืออีกฝั่งโดยไม่มีชั้นพักกลาง

Java SynchronousQueue: ส่งต่อแบบไม่มีชั้นวางพัก

พี่โชว์Engineering

ชื่อมีคำว่า Queue แต่ SynchronousQueue ไม่มีความจุเก็บ item เลย put จะสำเร็จเมื่อมี take มารับคู่กัน เหมาะกับ direct handoff ที่ต้องการ backpressure ทันทีครับ

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

public class Main {
  public static void main(String[] args) throws Exception {
    SynchronousQueue<String> handoff = new SynchronousQueue<>(true);
    ExecutorService pool = Executors.newSingleThreadExecutor();
    try {
      Future<Boolean> sent = pool.submit(
          () -> handoff.offer("report", 1, TimeUnit.SECONDS));
      String received = handoff.poll(1, TimeUnit.SECONDS);
      assert "report".equals(received);
      assert sent.get();
      assert handoff.isEmpty();
      assert handoff.remainingCapacity() == 0;
    } finally {
      pool.shutdownNow();
    }
  }
}

นึกถึงช่องส่งอาหารที่ไม่มีโต๊ะพัก คนครัวต้องเจอพนักงานเสิร์ฟตรงช่องพอดี ระบบจึงไม่สะสมงานเงียบ ๆ แต่ throughput จะผูกกับฝั่งที่ช้ากว่า Constructor ที่รับ true เลือก fairness แบบเข้าคิว ซึ่งคาดเดาลำดับง่ายขึ้นแต่มีค่า overhead เทียบกับค่าเริ่มต้น

ใช้ offer/poll พร้อม timeout เมื่อ thread ห้ามค้างตลอด และอย่าดู size() เพื่อคาดว่ามีงานรอ เพราะมันเป็นศูนย์เสมอ หากธุรกิจต้องทน burst ให้ใช้ queue ที่มี capacity ชัดและ metric วัด backlog แทน

Recap

  • ไม่มี storage ภายใน ทุก item ต้องจับคู่ producer-consumer
  • ใช้ timeout และ cancellation policy
  • เลือก fairness เมื่อ ordering สำคัญจริง
  • ใช้ bounded queue หากต้องดูดซับ burst