Được chỉnh sửa ngày 25/06/2021.
Chào mừng các bạn đã đến với bài học Java số 48, bài học về Threadpool phần thứ nhất. Đây là bài học trong chuỗi bài về lập trình ngôn ngữ Java của Yellow Code Books.
Như mình có nói, Java vốn tự hào là ngôn ngữ mạnh mẽ, một trong số đó là việc hỗ trợ các lập trình viên chúng ta thao tác với Thread. Và bạn đã chứng kiến điều đó thông qua khá nhiều các bài học liên quan đến các định nghĩa, cách sử dụng, và cả những vấn đề liên quan đến tổ chức, đồng bộ Thread nữa. Hôm nay, chúng ta lại tiếp tục làm quen một kiến thức nữa, cũng không nằm ngoài Thread. Một kiến thức nghe rất hay, Thread pool – Một cái hồ bơi dành cho Thread?!.
Kiến thức về Thread Pool này theo mình thì không nhiều, và cũng không khó để tiếp cận. Nhưng nói đến nó thì khá là vòng vo, với lại nó cần rất nhiều code minh họa. Do đó mình sẽ tách chúng ra làm 3 phần. Phần hôm nay chúng ta sẽ cùng làm quen với Thread Pool là gì. 2 phần sau sẽ cùng tìm hiểu 2 cách sử dụng Thread Pool.
Thread Pool Là Gì?
Như phần mở đầu mình có nói, đọc đến Thread Pool thì trong đầu bạn hiểu ngay nghĩa của nó là một cái Hồ bơi dành cho Thread?.
Nhưng theo mình, hiểu như vậy chẳng giúp gợi nhớ được gì. Để dễ tiếp cận hơn, bạn nên xem chữ Pool này như là một cái Hồ điều tiết thì hay hơn. Bạn tưởng tượng một thành phố nọ tuy có xây dựng các đường cống thoát nước rất hay, nhưng chẳng may một ngày kia có một cơn mưa rất lớn, lượng nước mưa chảy vào các cống này quá lớn khiến cho chúng không còn có khả năng thoát nước hiệu quả ra sông nữa. Khi này lãnh đạo thành phố mới nảy sinh sáng kiến nên xây dựng các hồ điều tiết. Thay vì nước mưa quá lớn gây ngập lụt đường phố, thì lượng nước này lại được trữ trong các hồ điều tiết. Đến khi cơn mưa dần giảm, nước trong hồ điều tiết lần lượt được xả vào trong các đường cống và thoát từ từ ra sông.
Bạn có thể so sánh một thành phố ở ví dụ trên chính là ứng dụng của chúng ta. Khi đó các đường cống thoát nước chính là các tài nguyên hệ thống đã cấp phát cho ứng dụng. Và lượng nước từ cơn mưa lớn chính là các Thread mà chúng ta tạo ra. Đồng ý là Thread giúp hệ thống xử lý các tác vụ song song, về cơ bản các tác vụ song song này giúp ứng dụng chạy mượt mà hơn. Nhưng nếu bạn tạo quá nhiều Thread và thực thi chúng cùng thời điểm, vô tình bạn tạo ra một áp lực rất lớn cho hệ thống. Càng nhiều Thread thì xem như lượng nước mưa càng lớn. Khi này các đường cống thoát nước sẽ không thể nào tải nổi nước mưa nữa, nó gây ra ngập lụt, tê liệt các hoạt động giao thông của thành phố. Điều này cũng sẽ tương tự với ứng dụng của bạn, hệ thống sẽ không thể nào đáp ứng tất cả các Thread đang hoạt động, ứng dụng sẽ dần trở nên chậm chạp, thiết bị sẽ nóng lên, gây ra nhiều hệ lụy không tốt cho cả người dùng lẫn thiết bị phần cứng. Chính vì lý do vậy mà chúng ta sẽ cần xây dựng một Hồ điều tiết cho ứng dụng, và kiến thức về Thread Pool cũng vì lẽ đó ra đời.
Khi Nào Thì Cần Dùng Đến Thread Pool?
Đến đây thì có lẽ bạn đã hiểu phần nào công năng của Thread Pool trong ứng dụng Java rồi. Nhưng liệu lúc nào chúng ta cũng cần đến Thread Pool không? Câu trả lời là không phải lúc nào cũng dùng đến Thread Pool đâu. Việc đầu tiên khi bạn muốn xây dựng các tác vụ song song cho ứng dụng, để chúng có thể chạy mượt mà hơn, là cứ tạo ra các Thread. Nếu không phải là làm game thì thường mỗi Thread bạn tạo ra trong ứng dụng có vòng đời khá ngắn, chỉ từ vài trăm mili giây cho đến vài chục giây là kết thúc rồi, nên bạn cũng chẳng cần phải nghĩ đến Thread Pool làm chi cho nó mệt. Nhưng nếu bạn xây dựng chức năng mà cùng một lúc có thể tạo ra rất nhiều Thread, có thể lên tới hàng trăm Thread hoặc hơn. Chẳng hạn chức năng up file lên mây, người dùng có thể chọn rất nhiều file để up (bạn có thể để ý cách Google Drive hoạt động khi up rất nhiều file). Với mỗi file như vậy sẽ cần 1 Thread để quản lý quá trình up. Khi này bạn nhất định phải xây dựng Thread Pool. Sau khi xây dựng xong một Pool, bạn chỉ việc chỉ định mỗi Pool như vậy có thể chứa bao nhiêu Thread, chẳng hạn 5 Thread đi, thì khi người dùng bắt đầu thao tác up file, hệ thống chỉ chạy tối đa 5 Thread một lần, tức sẽ up 5 file mỗi lần. Thread nào up xong thì Thread khác bắt đầu, đảm bảo cùng một lúc không thể quá 5 Thread up file được chạy, cứ như vậy cho đến khi nào up hết file của người dùng thì thôi. Bạn đã hiểu Thread Pool được dùng khi nào chưa nào.
Sử Dụng Thread Pool Như Thế Nào?
Lý thuyết là vậy, cũng không hoàn toàn khó hiểu đúng không bạn. Vậy thì áp dụng Thread Pool trong Java như thế nào, có khó không? Thực ra thì không khó đâu, vì Java đã cung cấp cho chúng ta một công cụ tuyệt vời, cách sử dụng công cụ này lại không khó tí nào cả. Công cụ mà mình nói đến, chính là một lớp có tên ThreadPoolExecutor.
Làm Quen Với ThreadPoolExecutor
Lớp này đã xây dựng sẵn cho bạn một hàng đợi có tên là Task Queue, và một Pool trong đó. Khi bạn có quá nhiều Thread (chính là các Runnable trong Application như hình dưới), thì thay vì cứ start chúng thành các Thread, bạn cứ “quăng” tất cả Runnable vào trong ThreadPoolExecutor đã khai báo. Tất cả các Runnable này sau đó được ThreadPoolExecutor để vào trong Task Queue. Và sẽ chỉ lấy ra đủ số lượng Runnable mà bạn đã chỉ định, để thực thi chúng thành các Thread. Dễ dàng thôi đúng không.
Cách thức sử dụng trực tiếp ThreadPoolExecutor được mình nói sau bài viết về cách sử dụng Thread Pool như mục dưới đây.
Làm Quen Với Executors, Executor Và ExecutorService
Trước khi tìm hiểu cách sử dụng ThreadPoolExecutor như thế nào, thì bài sau mình sẽ nói về cách sử dụng Executors, Executor và ExecutorService trước. Ôi sao đau đầu vậy?
Thực ra cái tên chính yếu bạn nên nhớ chỉ là ThreadPoolExecutor thôi, và cách hoạt động của nó mình đã minh họa ở mục trên đây. Nhưng ThreadPoolExecutor được xem như một cách sử dụng Thread Pool “thủ công”, tức là bạn phải điều khiển các tham số truyền vào theo đúng ý bạn, điều này tuy khá thú vị nhưng cần chúng ta phải có một ý niệm về Thread Pool trước đã. Chính vì vậy chúng ta gác ThreadPoolExecutor lại, nói sau. Chúng ta nói trước về Executors, Executor và ExecutorService.
Executors, Executor và ExecutorService được xem như bộ ba tiện ích, chúng giúp tách bạn ra khỏi ThreadPoolExecutor. Bằng cách xây dựng sẵn các phương thức và các ràng buộc mà bạn sẽ dễ dàng hơn trong việc hiểu và sử dụng Thread Pool. Bản chất của chúng vẫn là gọi lại ThreadPoolExecutor mà thôi. Thông qua bộ 3 tiện ích này, bạn sẽ có kiến thức gần như hoàn toàn đầy đủ về Thread Pool, khi đó tiếp cận ThreadPoolExecutor sẽ dễ dàng mà thôi.
Kết Luận
Bài học làm quen với Thread Pool nhẹ nhàng vậy thôi. Chúng ta sẽ thực hành việc tạo ra và điều khiển Thread Pool ở các phần sau nhé.
Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:
– Đánh giá 5 sao ở mỗi bài viết nếu thấy thích.
– Comment bên dưới mỗi bài viết nếu có thắc mắc.
– Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
– Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.
– Ủng hộ blog theo hướng dẫn ở thanh bên phải để blog ngày càng phát triển hơn.
Bài Kế Tiếp
Chúng ta sẽ xem cách thức tạo Thread Pool bằng bộ ba Executors, Executor và ExecutorService.
Chờ p2 mãi ad ơiiii
bài viết rất hay , các ý rất chi là sơ sài , mong add sớm add được quảng cáo vào để kiếm thật nhiều Money nhé. Kiến thức của Ad thật là thâm nho
Haha cảm ơn bạn, comment của bạn thật thú vị. Về việc gắn quảng cáo thì trước đây mình có làm, nhưng cũng không kiếm được bao nhiêu, mãi 3 năm đăng quảng cáo mới lấy của Google 2 triệu VND, chẳng bõ công cho các chi phí, mà lại làm chậm blog của mình nữa. Nên tức quá mình gỡ quảng cáo Google rồi. Giờ thì mọi thứ nhanh chóng trơn tru hẳn, vậy mình càng thích.
Mỗi tháng blog mình được bao nhiêu view thế anh? 😀