PlusMagi's Blog By Pitt Phunsanit Backend,Concurrency Java Concurrency: การบริหารจัดการ Thread Pool ด้วย ExecutorService และ ThreadPoolExecutor

Java Concurrency: การบริหารจัดการ Thread Pool ด้วย ExecutorService และ ThreadPoolExecutor

ในโลกของการพัฒนาแอปพลิเคชันระดับองค์กร (Enterprise Applications) ความสามารถในการขยายตัว (Scalability) และความเสถียรภายใต้ภาระงานสูงคือสิ่งสำคัญที่สุด การจัดการทรัพยากรการประมวลผลอย่างมีประสิทธิภาพ โดยเฉพาะอย่างยิ่งการควบคุมวงจรชีวิตของเธรด (Thread Lifecycle) จึงเป็นหัวใจหลักที่กำหนดว่าระบบจะสามารถรับมือกับ Traffic จำนวนมากได้อย่างไร หากเราสร้างเธรดใหม่ทุกครั้งที่มีงานเข้ามา จะเกิด Overhead มหาศาลและอาจนำไปสู่ปัญหา Resource Exhaustion ได้

แนวคิดของ Thread Pool: การจัดการทรัพยากรอย่างชาญฉลาด

Thread Pool คือกลไกที่เปลี่ยนจากการสร้างเธรดแบบ On-demand เป็นการใช้กลุ่มเธรดที่ถูกเตรียมไว้ล่วงหน้า (Pre-allocated) ซึ่งช่วยลดภาระในการเริ่มต้นและทำลายทรัพยากรเหล่านั้นได้อย่างมาก ใน Java Concurrency Framework เราใช้ ExecutorService เป็นอินเทอร์เฟซหลักในการจัดการวงจรชีวิตของ Pool และใช้คลาส ThreadPoolExecutor เพื่อให้เราสามารถปรับแต่งรายละเอียดเชิงลึกได้อย่างสมบูรณ์

ความแตกต่างระหว่าง ExecutorService และ ThreadPoolExecutor

  • ExecutorService: เป็นอินเทอร์เฟซระดับสูงที่ทำหน้าที่เป็นตัวควบคุม (Controller) ให้เราสามารถส่งงาน (Runnable/Callable) เข้าไปในระบบได้ง่ายๆ โดยไม่ต้องกังวลถึงรายละเอียดภายใน เป็นจุดที่นักพัฒนาส่วนใหญ่ควรเริ่มต้นใช้งาน
  • ThreadPoolExecutor: คือการใช้งานจริง (Implementation) ที่ให้ความยืดหยุ่นสูงสุดในการกำหนดพารามิเตอร์ต่างๆ เช่น ขนาดเธรดขั้นต่ำ (Core Pool Size), ขนาดเธรดสูงสุด (Maximum Pool Size), และนโยบายการปฏิเสธงาน (Rejection Policy) เหมาะสำหรับสถาปนิกที่ต้องการควบคุมระบบอย่างละเอียด

ตัวอย่างการใช้งาน ExecutorService ใน Java

การใช้ ExecutorService ช่วยให้โค้ดของเรามีความสะอาดและจัดการทรัพยากรได้ดีกว่าการสร้างเธรดด้วยตนเองมาก นี่คือตัวอย่างการจำลองการทำงานแบบขนาน (Parallel Processing) โดยการส่งงาน (Runnable) จำนวนมากเข้าสู่ Pool ที่กำหนดขนาดไว้ที่ 5 เธรด

Java

import java.util.concurrent.*;

public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 1. สร้าง ExecutorService ด้วยขนาดเธรดคงที่ (Fixed Size Pool)
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // 2. สร้างงาน (Runnable) 10 ชิ้น
        for (int i = 1; i <= 10; i++) {
            final int taskNumber = i;
            // ส่งงานเข้า Pool
            executor.execute(() -> {
                System.out.println("Task " + taskNumber + " started by thread: " + Thread.currentThread().getName());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println("Task " + taskNumber + " finished.");
            });
        }

        // 3. ปิด Pool และรอให้งานทั้งหมดเสร็จสิ้น (Shutdown)
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                System.err.println("Pool did not terminate in time.");
            }
        } catch (InterruptedException e) {
            System.err.println("Shutdown interrupted.");
        }
    }
}

บทสรุป: การบริหารจัดการทรัพยากรอย่างยั่งยืน

การทำความเข้าใจและใช้ ExecutorService อย่างถูกต้องถือเป็นทักษะสำคัญสำหรับ Senior Developer เพราะมันช่วยให้เราเปลี่ยนจากการเขียนโค้ดที่เน้น ‘การทำงาน’ (How to run) ไปสู่การเขียนโค้ดที่เน้น ‘การจัดการทรัพยากร’ (How to manage resources) ทำให้ระบบมีความเสถียรสูง สามารถรองรับภาระงานที่เพิ่มขึ้นได้อย่างมีประสิทธิภาพ และที่สำคัญคือช่วยป้องกันปัญหา Resource Exhaustion ที่อาจเกิดขึ้นจากการสร้างเธรดจำนวนมากเกินความจำเป็น การใช้ Pool อย่างเหมาะสมจึงเป็นรากฐานสำคัญของการออกแบบระบบระดับ Enterprise ที่สมบูรณ์

Exit mobile version