ทั้งคู่เป็น Interface ใน **Executor Framework** (Java 5+) ใช้สำหรับจัดการ Thread Pool และ Asynchronous Execution
ตารางเปรียบเทียบ
| ลำดับ | หัวข้อ | Executor | ExecutorService |
| 1 | Hierarchy | **Parent Interface** (Root) | **Sub-interface** extends Executor |
| 2 | Main Method | void execute(Runnable command) | Future<?> submit(Task) (+ execute) |
| 3 | Return Value | **void** - ไม่ได้ผลลัพธ์ | Future - ได้ผลลัพธ์/Exception/Status |
| 4 | Task Types | แค่ Runnable | Runnable + Callable<V> |
| 5 | Lifecycle Management | ไม่มี (ไม่มี shutdown) | shutdown(), shutdownNow(), awaitTermination() |
| 6 | Task Control | ไม่ได้ (fire-and-forget) | Cancel, Check status, Get result, Timeout |
| 7 | Factory Methods | ไม่มี (เป็น interface) | มีใน Executors class |
Executor - Basic Fire-and-Forget
public class ExecutorExample {
public static void main(String[] args) {
// Executor คือ functional interface (1 method)
Executor executor = Runnable::run; // Simple: run in current thread
// หรือใช้ Thread Pool
Executor threadPoolExecutor = Executors.newFixedThreadPool(4);
executor.execute(() -> {
System.out.println("Running in thread: " + Thread.currentThread().getName());
// ไม่ได้ return ค่า, ไม่รอผล, ไม่ cancel ได้
});
// ❌ ไม่มี shutdown() - ต้อง cast หรือใช้ ExecutorService แทน
}
}
ExecutorService - Full Featured
public class ExecutorServiceExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 1. submit(Runnable) → Future>
Future> future1 = executor.submit(() -> {
System.out.println("Runnable task");
});
future1.get(); // รอจบ (return null)
// 2. submit(Callable) → Future
Future future2 = executor.submit(() -> {
Thread.sleep(1000);
return "Result from Callable";
});
System.out.println("Result: " + future2.get()); // Block จนกว่าจะได้ผล
// 3. submit(Runnable, T) → Future
Future future3 = executor.submit(() -> {
System.out.println("Runnable with result");
}, 42); // ค่าที่จะ return
System.out.println("Fixed result: " + future3.get()); // 42
// 4. invokeAll - รอทั้งหมด
List> tasks = List.of(
() -> { sleep(500); return "Task 1"; },
() -> { sleep(300); return "Task 2"; }
);
List> futures = executor.invokeAll(tasks);
for (Future f : futures) {
System.out.println("invokeAll: " + f.get());
}
// 5. invokeAny - รอตัวแรกที่เสร็จ
String fastest = executor.invokeAny(tasks);
System.out.println("Fastest: " + fastest);
// Shutdown
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
}
static void sleep(long ms) {
try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}
Future Interface - ควบคุม Task
| Method | คำอธิบาย |
get() | Block จนกว่าจะเสร็จ, คืนผลลัพธ์ (หรือ throw Exception) |
get(timeout, unit) | Block พร้อม Timeout, throw TimeoutException |
cancel(mayInterruptIfRunning) | พยายามยกเลิก task |
isDone() | Task เสร็จแล้วหรือยัง (normal/exception/cancel) |
isCancelled() | Task ถูก cancel หรือไม่ |
CompletableFuture (Java 8+) - Async Composition
ExecutorService executor = Executors.newFixedThreadPool(4);
// SupplyAsync - run async, return CompletableFuture
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
sleep(1000);
return "Hello";
}, executor);
// ThenApply - chain transformation (non-blocking)
CompletableFuture upper = future.thenApply(String::toUpperCase);
// ThenAccept - consume result
upper.thenAccept(result -> System.out.println("Result: " + result));
// ThenCompose - chain async operations
CompletableFuture chained = future
.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World", executor));
// Exception handling
future.exceptionally(ex -> "Error: " + ex.getMessage());
// Combine
CompletableFuture.allOf(future1, future2, future3).join(); // Wait all
CompletableFuture.anyOf(future1, future2).join(); // Wait any
สรุป: เมื่อไหร่ใช้อะไร?
| สถานการณ์ | ใช้ | เหตุผล |
| แค่รัน background task, ไม่ต้องการผลลัพธ์ | Executor.execute() | Simple, lightweight |
| ต้องการผลลัพธ์, Exception handling | ExecutorService.submit(Callable) | Future ได้ result/exception |
| ต้องการควบคุม lifecycle (shutdown, cancel) | ExecutorService | มี lifecycle methods |
| Parallel tasks, รอทั้งหมด/ตัวแรก | ExecutorService.invokeAll/Any | Built-in coordination |
| Complex async chaining, composition | CompletableFuture | Fluent API, non-blocking composition |
| Fire-and-forget ใน Framework code | Executor (parameter) | Decouple from concrete implementation |
Best Practice: Program to Interface
// Good: รับ Executor (ยืดหยุ่น สามารถส่ง ExecutorService, ForkJoinPool, Custom ได้)
public void processAsync(Executor executor, Runnable task) {
executor.execute(task);
}
// เรียกใช้
processAsync(Executors.newFixedThreadPool(4), () -> System.out.println("Work"));
processAsync(ForkJoinPool.commonPool(), () -> System.out.println("Work"));
processAsync(r -> new Thread(r).start(), () -> System.out.println("Work")); // Custom