[JAVA] Thread Pool ใน Java

ช่วงนี้งานเยอะครับ ผมได้รับมอบหมายงานให้ลองปรับระบบงานเดิม ให้มันรองรับงานได้มากขึ้น และหนึ่งในเทคนิคที่ผมเลือกใช้ การทำงานแบบ Asynchronous ครับ โดยการทำงานแบบนี้สิ่งคนสั่ง สั่งงานเสร็จปุ๊บ ไม่ต้องรอผลลัพธ์ครับ แล้วให้ระบบมันทำงานต่อไปจนเสร็จ และแจ้งค่อยแจ้งผลลัพธ์ให้ Client รับทราบครับ แล้ว ThreadPool มันเกี่ยวยังไงหละ เจ้า ThreadPool มันเป็นวิธีการนึงที่ช่วยในการจัดการกับ Resource ครับ ถ้าเป็นเมื่อก่อนเวลาเราจะแตกงานให้ใช้ CPU ของเครื่องให้มันคุ้มค่าสิ่งที่ทำกัน คือ การ New Thread แยกเลยครับ ตาม Code ตัวอย่างครับ ปล. Code นี้มีปัญหานะครับ Run ไปเรื่อยๆ

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadTest {

 public static void main(String[] args) throws InterruptedException {

  for (int i = 0; i < 20; i++) {
   final int number = i;
   Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
     int result = number * 2;
     System.out.println("Running " + number);
     System.out.println("Running " + number + " Value = " + result);
     sleep(2000);
     System.out.println("Finishing " + number);
    }
   });
   thread.start();
  }

 }

 private static void sleep(int value) {
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}

จาก Code ในข้างต้น ถ้ามีงานสัก 100 ชิ้น และต้องการแตก Thread จะพบปัญหาของการไปเขียน Thread แยกเอง ถ้าไม่เชี่ยว หรือเชี่ยวแล้วอย่าทำครับ เพราะ

ทำอะไรไว้ ต้องไปจัดการให้เรียบร้อยด้วยนะครับ

เพราะ เราต้องการคุมเกม แต่ถ้าเกิด Exception ขึ้นมาแล้ว เราต้องจัดการกับ Thread ที่มีปัญหาเองนะครับ ไม่งั้นมันจะแอบกิน Resource ของระบบไปเรื่อยๆจน System Down ลงไปครับ หรือ  ถ้าเราต้องการควบคุมว่ามีแต่ 5 Thread เท่าที่นั้นสามารถทำงานได้พร้อมกัน โอ้ววต้องไปเขียน Semaphore กันวุ่นวายเลย

พระเอกของเราครับ แนวคิดของ ThreadPool จึงเกิดขึ้นมาครับ เพื่อมาเป็นตัวช่วยในการจัดการงานทั้งหมดให้งาน หรือใช้ Resouce ได้คุ้มค่า เพราะในแนวคิดของการ Caching Thread ทำงานเดียวกัน แต่ทำไมเยอะแยะสร้างตามที่มันสามารถทำงานได้พร้อมกัน และเมื่อมันทำงานเสร็จ โดย Thread ที่ทำงานเสร็จแล้วก็จะกลับไปเป็นสถานะ Idle และรอการ Reuse หรือถูกทำลายไปครับ สำหรับใน Java มีตัว Executor Interface เตรียมมาไว้ให้แล้วครับ มาดูตัวอย่าง Code บางส่วนกัน ตัวอย่าง ผมได้กำหนดงานมา 100 ชึ้น โดยสามารถทำพร้อมกันได้ทีละ 10 ชิ้น และงานแต่ละขึ้นจบในตัวไม่ได้ Return ค่าอะไรออกมาด้วยครับ

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExcutorServiceTest {

 public static void main(String[] args) throws InterruptedException {

  // กำนดไปเลยว่ามี 10 Thread รอทำงาน เอาง่ายเรา Block ให้งานทำงานพร้อมกันได้ทีละ 10 Thread เท่านั้น
  ExecutorService executor = Executors.newFixedThreadPool(10);
  System.out.println("Start ThreadPoolTaskExecutor");
  // ส่งงานเข้าไป 100 Thread เลยยย
  for (int i = 0; i < 100; i++) {
   final int number = i;
   executor.execute(new Runnable() {
    @Override
    public void run() {
     int result = number * 2;
     System.out.println("Running " + number);
     System.out.println("Running " + number + " Value = " + result);
     sleep(2000);
     System.out.println("Finishing " + number);
    }
   });
  }

  System.out.println("Waiting...");

  //รอจนกว่างานทั้ง 100 ชึ้นทำงานเสร็จแล้ว สังเกตุดีๆ ใน Loop มันเริ่มจาก 0 นะครับ
  executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
  //ปิดรับงานครับ
  executor.shutdown();

  System.out.println("Done");
 }

 private static void sleep(int value) {
  try {
   Thread.sleep(value);
  } catch (InterruptedException e) {
   throw new RuntimeException(e);
  }
 }
}

สำหรับผมที่ต้องเขียน Blog นี้ขึ้นมา เพราะงงครับ โยกจาก C# มา แล้วมี Java และมี Spring Framework ซึ่งทำให้ผมงงยิ่งไปอีกครับ ตัว Spring มันมี Class แยกไป ผมเลยเขียน Blog ไว้ เพื่อจัดการความรู้ตัวเอง หากคนที่ผ่านมาอ่านแล้วมันเขียนผิดสามารถทักให้แก้ไขได้นะครับ


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.