กรอบงานแม่ครอบงานลูกสามก้อนบนโต๊ะมิ้นต์ มีจุดรวมผลสีอำพัน

StructuredTaskScope.open + Joiner: รวมงานย่อยแบบ structured (JDK 25 preview)

น้องกายEngineering

เวลาเรียก API พร้อมกันหลายตัว แล้วอยากให้ล้มทั้งชุดเมื่อตัวใดตัวหนึ่งพัง — โมเดลเก่าที่โยน Future ไปทั่วกองมักจัดการยกเลิกยากครับ

Structured Concurrency ใน JDK 25 ยังเป็น preview ตาม JEP 505 แต่ API เปลี่ยนชัด: ไม่สร้าง new StructuredTaskScope...() ตรง ๆ แล้ว ให้เปิดด้วย StructuredTaskScope.open(...) แล้วเลือกนโยบายผ่าน Joiner

แนวคิดสั้น ๆ:

  1. เปิด scope ใน try-with-resources
  2. fork งานย่อย (มักรันบน virtual threads)
  3. join() รอทั้งชุดตามนโยบาย Joiner
  4. ออกจาก scope = งานลูกที่ค้างถูกจัดการตามสเปก ไม่ปล่อย thread หลุด

ตัวอย่างนโยบายที่เจอบ่อยในเอกสาร:

  • open() ไม่ส่ง Joiner → รอให้สำเร็จครบ หรือล้มเมื่อตัวใดล้ม
  • Joiner.anySuccessfulResultOrThrow() → ได้ผลจากตัวแรกที่สำเร็จ (คล้าย ShutdownOnSuccess เดิม)

บล็อกด้านล่างเป็น fragment อ่านแนวคิด (preview API — เปิด --enable-preview ตามรุ่นที่ทีมใช้)

บล็อกด้านล่างเป็น fragment สำหรับอ่านแนวคิด (ไม่ใช่ suite ที่รันใน CI นี้)

// Conceptual JDK 25 preview shape — enable preview flags in real builds
// try (var scope = StructuredTaskScope.open()) {
//     var a = scope.fork(() -> fetchA());
//     var b = scope.fork(() -> fetchB());
//     scope.join(); // policy from open()
// }

Recap

  • อ่าน JEP 505 ก่อนย้ายจาก API preview รอบก่อน
  • แทนคอนสตรัคเตอร์เก่าด้วย StructuredTaskScope.open + Joiner
  • ใช้คู่กับ virtual threads เมื่องานเป็น I/O หนัก
  • อย่าลืมว่ายัง preview — เปิด flag ให้ครบใน CI