นากกายปล่อยการ์ดงานสามใบเข้าช่องพูล แล้วรอกล่องผลรวมสีอำพันบนโต๊ะมิ้นต์

ExecutorService.invokeAll: ส่งงานหลายชิ้นแล้วรอผลพร้อมกัน

น้องกายEngineering

ถ้ามีงานอิสระหลายชิ้นที่อยากยิงพร้อมกันแล้วรอให้ครบ invokeAll ช่วยจัดคิวให้

ตามเอกสาร ExecutorService เมธอด invokeAll(Collection) ส่ง Callable ทั้งหมดเข้า executor แล้ว บล็อกจนกว่างานทุกชิ้นเสร็จ (สำเร็จหรือโยน exception ใน Future) จากนั้นคืน List<Future> ตามลำดับเดียวกับอินพุต

มี overload ที่รับ timeout ด้วย — ถ้าหมดเวลางานที่ยังไม่เสร็จอาจถูกยกเลิก

import java.util.List;
import java.util.concurrent.Callable;
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 {
    ExecutorService exec = Executors.newFixedThreadPool(2);
    try {
      List<Callable<Integer>> tasks = List.of(
          () -> 1 + 1,
          () -> 2 * 3,
          () -> 7
      );
      List<Future<Integer>> futures = exec.invokeAll(tasks, 2, TimeUnit.SECONDS);
      int sum = 0;
      for (Future<Integer> f : futures) {
        sum += f.get();
      }
      if (sum != 15) {
        throw new IllegalStateException("sum=" + sum);
      }
      System.out.println("ok " + sum);
    } finally {
      exec.shutdown();
      if (!exec.awaitTermination(2, TimeUnit.SECONDS)) {
        exec.shutdownNow();
      }
    }
  }
}

Recap

  1. ใช้ invokeAll เมื่อต้องรอผลทุกงานก่อนไปต่อ
  2. ลำดับ Future ตรงกับลำดับ Callable
  3. เลือก overload มี timeout ถ้างานอาจค้าง
  4. ปิด executor ใน finally เสมอ