Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ความแตกต่างระหว่าง Executor และ ExecutorService ใน Java

ทั้งคู่เป็น Interface ใน **Executor Framework** (Java 5+) ใช้สำหรับจัดการ Thread Pool และ Asynchronous Execution

ตารางเปรียบเทียบ

ลำดับหัวข้อExecutorExecutorService
1Hierarchy**Parent Interface** (Root)**Sub-interface** extends Executor
2Main Methodvoid execute(Runnable command)Future<?> submit(Task) (+ execute)
3Return Value**void** - ไม่ได้ผลลัพธ์Future - ได้ผลลัพธ์/Exception/Status
4Task Typesแค่ RunnableRunnable + Callable<V>
5Lifecycle Managementไม่มี (ไม่มี shutdown)shutdown(), shutdownNow(), awaitTermination()
6Task Controlไม่ได้ (fire-and-forget)Cancel, Check status, Get result, Timeout
7Factory 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 handlingExecutorService.submit(Callable)Future ได้ result/exception
ต้องการควบคุม lifecycle (shutdown, cancel)ExecutorServiceมี lifecycle methods
Parallel tasks, รอทั้งหมด/ตัวแรกExecutorService.invokeAll/AnyBuilt-in coordination
Complex async chaining, compositionCompletableFutureFluent API, non-blocking composition
Fire-and-forget ใน Framework codeExecutor (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