Quản lý thread pool là gì, tìm hiểu về thread pool trong java

     

Thread Pool Là một trong những yếu tố chính tác động tới hiệu năng của các chương trình lớn, các ứng dụng đòi hỏi xử lý đồng thời nhiều nhiệm vụ cùng lúc.

Bạn đang xem: Quản lý thread pool là gì, tìm hiểu về thread pool trong java

Khi nào bạn cần sử dụng đến thread pool, hiểu nôm na là có 1 hồ chứa lưu giữ các thread để khi cần bạn có thể lấy ra để dùng, khi dùng xong thì lại cất vào đó. Trước khi đi sâu vào việc mô tả chi tiết các tính năng thread pool mình sẽ giới thiệu lại với các bạn Thead trong java.

 ví dụ này, khi thực thi chương trình sẽ in ra ở console

Demo about a java program

 

public class Example1{public static void main(String<> args){System.out.println(“Demo about a java program”);}}

 

Chương trình trên chỉ có 1 thread là main thread và chương trình sẽ được chạy tuần từ từ trên xuống dưới.

public class Example1{public static void main(String<> args){System.out.println(“Demo about a java program”);

System.out.println(“Demo about a java program 1”);}

}}

Thì Demo about a java program 1 sẽ được in ngay dưới Demo about a java program

Trong thực tế các ứng dụng bạn cần phải thực thi nhiều công việc gần như là song song để giảm bớt thời gian chờ.

Trong Java bạn có thể làm điều này bằng cách sử dụng Thread, có 2 cách để khai báo 1 Thread

Thực hiện extend lớp ThreadThực hiện implement interface Runnable.

 

Thực hiện extend lớp Thread

 

class ThreadTest extends Thread{public void run(){System.out.println(“Make a thread…”);}public static void main(String args<>){ThreadTest t1=new ThreadTest();t1.start();}}Bây giờ ngoài Thread main của chương trình thì còn có thêm 1 thread t1 nữa chúng ta vừa tạo ra.

2) Thực hiện implement interface Runnable

class ThreadTest1 implements Runnable{public void run(){System.out.println(“Make a thread…”);}

public static void main(String args<>){ThreadTest1 m1=new ThreadTest1();Thread t1 =new Thread(m1);t1.start();}}

Nếu giả sử chương trình lớn và bạn tạo ra rất nhiều thread để thực thi thì điều gì sẽ xảy ra, tất nhiên nó sẽ tốn tài nguyên của hệ thống vì việc tạo mới 1 Thread thường sẽ rất tốn tài nguyên, bạn có thể tạo 1 hay 10 Thread nhưng nếu lên đến hàng 100 và 1000 thì đây là vấn đề khác.

Vì điều này mà Java đã sinh ra một framework Executive áp dụng dụng Thread Pool để giải quyết vấn đề này.

Hình dưới đây minh họa cho Thread pool sẽ xử lý cá task, nếu 1 trong các thread hoàn thành task thì nó sẽ lấy 1 task từ hàng đợ và thực thi, khi tất cả task hoàn thành tất cả các thread trong pool sẽ đợi để thực hiện task khác nếu được đẩy vào queue.

Tạo ThreadPool

*

Java Concurrency API hỗ trợ ThreadPool sau:

Single-threaded pool: chỉ tạo ra một Thread thực thi, các task sẽ được thực hiện tuần tự.Cached thread pool: Việc tạo ra thread sẽ được tính toán nếu cần, các task sẽ được sử dụng lại các thread đã tạo. Nên áp dụng với số lượng task ít.Fixed thread pool: tạo ra một số thread trong pool trước để phục vụ các task, nếu số lượng task lớn hơn số thread trong pool thì sẽ phải đợi trong QueueFork/Join pool: sử dụng Fork/ Join Framework bằng cách tự động chia nhỏ công việc tính toán cho các core xử lý. (Tính toán song song), sau đó sẽ gộp. Fork sau đó join.

Executor

*

Executor là một class trong gói java.util.concurrent, là một đối tượng chịu trách nhiệm quản lý các luồng và thực hiện các tác vụ Runnable được yêu cầu xử lý. Nó tách riêng các chi tiết của việc tạo Thread, chúng ta chỉ cần tập trung task mà không quan tâm đến quản lý thread.

Tạo một Executor bằng cách sử dụng một trong các phương thức được cung cấp bởi lớp tiện ích Executors như sau:

newSingleThreadExecutor(): trong ThreadPool chỉ có 1 Thread và các task sẽ được xử lý một cách tuần tự.newCachedThreadPool():sẽ có 1 số lượng nhất định thread để sử dụng lại, nhưng vẫn sẽ tạo mới thread nếu cần. Mặc định nếu một Thread không được sử dụng trong vòng 60 giây thì Thread đó sẽ bị hủy.newFixedThreadPool(int n): trong Pool chỉ có n Thread để xử lý nhiệm vụ, các yêu đầu đến sau sẽ đưa vào hàng đợi.newScheduledThreadPool(int corePoolSize): tương tự như newCachedThreadPool() nhưng sẽ có thời gian delay giữa các Thread.newSingleThreadScheduledExecutor(): tương tự như newSingleThreadExecutor() nhưng sẽ có khoảng thời gian delay giữa các Thread.

 Code chạy thử

Chúng ta sẽ lấy ví dụ đầu bài để code luôn nhé.

Tạo một class implement Runnable để xử lý, RunnableTest này cũng sẽ được dùng để đưa vào các ThreadPool để tính toán sau này.

package cdspninhthuan.edu.vn.executor;

public class RunnableTest implements Runnable {String name;public RunnableTest(String name){this.

Xem thêm: Trẻ 6 Tháng Ăn Được Hoa Quả Gì, Trẻ 6 Tháng Tuổi Ăn Hoa Quả Gì

name = name;}


Overridepublic void run() {try {// Bắt đầu xử lýSystem.out.println(Thread.currentThread().getName() + ” Starting process ” + name);Thread.sleep(500);System.out.println(Thread.currentThread().getName() + ” Finished process ” + name);} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String args<>){ //Theo cách truyền thống thì để thực thi RunnableTest ta phải tạo mới 1 Thread sau đó truyền RunnableTest vào.new Thread(new RunnableTest(“T1”)).start();}}

Test code với newSingleThreadExecutor

package cdspninhthuan.edu.vn.executor;

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

public class SingleThreadPoolExample {public static void main(String<> args) {ExecutorService executor = Executors.newSingleThreadExecutor();checkTime(executor);}static void checkTime(ExecutorService executor) {long begin = System.currentTimeMillis();for (int i = 0; i executor.execute(new RequestHandler(“request-” + i));}executor.shutdown(); // Không cho threadpool nhận thêm nhiệm vụ nào nữa

while (!executor.isTerminated()) {// Chờ xử lý hết các request còn chờ trong Queue …}long end = System.currentTimeMillis();long totalTime = (end – begin)/1000;System.out.println(“Total time “+totalTime);}}

// OUTPUT:

pool-1-thread-1 Starting process request-97

pool-1-thread-1 Finished process request-97

pool-1-thread-1 Starting process request-98

pool-1-thread-1 Finished process request-98

pool-1-thread-1 Starting process request-99

pool-1-thread-1 Finished process request-99

Total time 50

Trong pool chỉ có duy nhất 1 thread, do đó việc xử lý các task sẽ được thực hiện tuần tự, thời gian thực hiện là 50S.

newFixedThreadPool()

package cdspninhthuan.edu.vn.executor;

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

public class FixedThreadPoolExample {public static void main(String<> args) throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(5);

// Có 100 request tới cùng lúccheckTime(executor);}

static void checkTime(ExecutorService executor) {long begin = System.currentTimeMillis();for (int i = 0; i executor.execute(new RunnableTest(“request-” + i));}executor.shutdown(); // Không cho threadpool nhận thêm nhiệm vụ nào nữa

while (!executor.isTerminated()) {// Chờ xử lý hết các request còn chờ trong Queue …}long end = System.currentTimeMillis();long totalTime = (end – begin)/1000;System.out.println(“Total time “+totalTime);}}

 

pool-1-thread-4 Finished process request-94

pool-1-thread-4 Starting process request-99

pool-1-thread-1 Finished process request-95

pool-1-thread-2 Finished process request-96

pool-1-thread-3 Finished process request-97

pool-1-thread-5 Finished process request-98

pool-1-thread-4 Finished process request-99

Total time 10

Với loại này thực hiện cấp 5 thread cho pool, chương trình sẽ sử dụng 5 thread trong pool, các task sẽ chia sẻ nhau 5 thread này. Bạn có thể nhìn thấy chương trình giờ chỉ chạy hết 10s thay vì 50s như ví dụ trên.

newCachedThreadPool()

package cdspninhthuan.edu.vn.executor;

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

public class CachedThreadPoolExample {public static void main(String<> args) throws InterruptedException {ExecutorService executor = Executors.newCachedThreadPool();long begin = System.currentTimeMillis();// Có 100 request tới cùng lúc

for (int i = 0; i executor.execute(new RunnableTest(“request-” + i));Thread.sleep(20);}executor.shutdown(); // Không cho threadpool nhận thêm nhiệm vụ nào nữa

while (!executor.isTerminated()) {// Chờ xử lý hết các request còn chờ trong Queue …}long end = System.currentTimeMillis();long totalTime = (end – begin)/1000;System.out.println(“Total time “+totalTime);}}

 

pool-1-thread-1 Finished process request-95

pool-1-thread-2 Finished process request-96

pool-1-thread-3 Finished process request-97

pool-1-thread-25 Finished process request-98

pool-1-thread-4 Finished process request-99

Total time 2

Chương trình chạy nhanh hơn hẳn xuốn con 2S vì số thread được tạo thoải mái( lưu ý với cách này chỉ nên dùng với các task vụ có thời gian xử lý nhỏ, và nên kiểm soát được số thread tạo ra không sẽ nguy hiểm), và lưu ý các thread có thể sử dụng lại giữa các task.

Qua bài viết này hy vọng các bạn biết được cách để sử dụng ThreadPool trong java, đừng khi nào cũng create new Thread khi xử lý lập trình đa Thread nữa nhé. Cảm ơn các bạn đã theo dõi.

Mình giới thiệu với các bạn 1 số quyển sách hay khi học về xử lý đồng bộ và hiệu năng.

Java Concurrency in PracticeJava PerformanceThinking in Java (4th Edition)Effective Java (2nd Edition)Java Puzzlers : Traps, Pitfalls, And Corner CasesHead First Java, 2nd Edition


Chuyên mục: Tài liệu