Demo lợi ích của sử dụng multithreading trong Java

Chào mừng các bạn đã đến với thachleblog. Bài viết hôm nay, mình sẽ giới thiệu một chủ đề cực kỳ hay ho trong lập trình Java, đó là multithreading. Multithreading là một kỹ thuật lập trình cực kỳ quan trọng, nhưng đa phần với sinh viên mới ra trường hoặc đi làm nhưng ít có cơ hội làm việc trực tiếp, hiểu biết về multithreading cũng như khả năng áp dụng còn khá mơ hồ. Do đó, với loạt bài chia sẻ về multi thread và concurrency bắt đầu từ bài này, mình hy vọng sẽ có thể làm rõ các vấn đề trong multithreading và concurrency, mình rất mong nhận được những góp ý từ các bạn.

Giới thiệu

Multithreading định nghĩa theo kiểu hàn lâm là một kỹ thuật giúp cho một chương trình có khả năng xử lý đồng thời nhiều công việc nhằm tăng hiệu suất công việc và tận dụng tốt tài nguyên của hệ thống.

Lưu ý là multithreading chỉ có thể chạy đồng thời trên máy tính multi core, đối với máy 1 core, các thread sẽ được switch liên tục trên 1 core để chạy.

Ví dụ vui

Phòng trọ mình dọn dẹp cuối tháng, có các công việc cần phải làm được liệt kê như sau:
– Lau nhà cần 15′
– Sắp xếp đồ đạc cần 15’
– Dọn đổ rác cần  10’
Mặc dù phòng mình có 3 người, nhưng nếu mình sai thằng em mình làm tất thì sẽ mất tầm 40’. Nhưng nếu mình và bạn còn lại phụ cùng làm thì mỗi thằng mất 10 – 15’, toàn bộ công việc dọn dẹp hoàn thành trong khoảng 15’.
Giả sử chương trình là dọn nhà, và 3 thằng là tài nguyên của hệ thống thì khả năng 3 thằng cùng làm song song chính là ứng dụng multi thread. Mình sẽ có chương trình cụ thể để mô phỏng ví dụ.
Sau đây là ví dụ về cách implement multi thread bằng cách implement interface Runable
Nếu như mình cho thằng em mình làm tất, giả sử ở đây mỗi việc tốn 5s (đỡ mất công chờ):

Class NonmultiThread minh họa công việc được thực hiện bằng cách thông thường:

  1. package thach.le;
  2. import java.util.concurrent.TimeUnit;
  3. public class NonMultiThread {
  4. // clean ground, it takes 5s
  5. public static void cleanGround() throws InterruptedException {
  6. System.out.println("== I am cleanning ground...");
  7. TimeUnit.SECONDS.sleep(5);
  8. System.out.println("== Complete clean ground!");
  9. }
  10.  
  11. // clean ground, it takes 5s
  12. public static void sortStuff() throws InterruptedException {
  13. System.out.println("== I am sorting stuff...");
  14. TimeUnit.SECONDS.sleep(5);
  15. System.out.println("== Complete sort stuff!");
  16. }
  17.  
  18. // clean ground, it takes 5s
  19. public static void throwGarbage() throws InterruptedException {
  20. System.out.println("== I am throwing garbage...");
  21. TimeUnit.SECONDS.sleep(5);
  22. System.out.println("== Complete throw garbage!");
  23. }
  24.  
  25. public static void main(String[] args) throws InterruptedException {
  26. System.out.println("I am doing house work...");
  27. long start = System.nanoTime();
  28.  
  29. cleanGround();
  30. sortStuff();
  31. throwGarbage();
  32.  
  33. long elapsedTime = System.nanoTime() - start;
  34. System.out.println("Complete house work!");
  35. System.out.println("Elapsed time: " + elapsedTime / 1000000000.0 + "(s)");
  36. }
  37. }

Kết quả, mỗi việc mất 5s, trung bình mất khoảng 15s

loi ich multi thread

Multithreading

Các công việc implement Runable theo phương pháp cổ điển, ở các bài viết sau mình sẽ implement multithreading bằng lamda expression:

Class CleaningGround

  1. package thach.le.housework;
  2. import java.util.concurrent.TimeUnit;
  3. public class CleaningGround implements Runnable {
  4. @Override
  5. public void run() {
  6. System.out.println(== I am cleanning ground...);
  7. try {
  8. TimeUnit.SECONDS.sleep(5);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. System.out.println(== Complete clean ground!);
  13. }
  14. }

Class SortingStuff

  1. package thach.le.housework;
  2. import java.util.concurrent.TimeUnit;
  3. public class SortingStuff implements Runnable {
  4.  
  5. @Override
  6. public void run() {
  7. System.out.println(== I am sorting stuff...);
  8. try {
  9. TimeUnit.SECONDS.sleep(5);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. System.out.println(== Complete sort stuff!);
  14. }
  15. }

Class ThrowingGarbage

  1. package thach.le.housework;
  2. import java.util.concurrent.TimeUnit;
  3. public class ThrowingGarbage implements Runnable {
  4. @Override
  5. public void run() {
  6. System.out.println(== I am throwing garbage...);
  7. try {
  8. TimeUnit.SECONDS.sleep(5);
  9. } catch (InterruptedException e) {
  10. // TODO Auto-generated catch block
  11. e.printStackTrace();
  12. }
  13. System.out.println(== Complete throw garbage!);
  14. }
  15. }

Class Test

  1. package thach.le.housework;
  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;
  4. public class Test {
  5. public static void main(String[] args) {
  6. System.out.println(I am doing house work...);
  7. long start = System.nanoTime();
  8.  
  9. SortingStuff sortingStuff = new SortingStuff();
  10. CleaningGround cleanGround = new CleaningGround();
  11. ThrowingGarbage throwingGarbage = new ThrowingGarbage();
  12. ExecutorService executor = Executors.newFixedThreadPool(3);
  13.  
  14. executor.execute(throwingGarbage);
  15. executor.execute(sortingStuff);
  16. executor.execute(cleanGround);
  17.  
  18. // Wait until all threads are finish
  19. executor.shutdown();
  20. while (!executor.isTerminated()) {
  21. }
  22.  
  23. long elapsedTime = System.nanoTime() - start;
  24. System.out.println(Complete house work!);
  25. System.out.println(Elapsed time: + elapsedTime / 1000000000.0 + (s));
  26. }
  27. }

Kết quả

result_multithread.jpg
Thật ấn tượng, chỉ tốn 5s!

Vừa rồi là ví dụ đơn giản về sử dụng multi thread trong Java, chúng ta có thể thấy, việc sử dụng multi thead sẽ tiết kiệm cả thời gian lẫn tài nguyên hệ thống (máy 2, 3 core mà chỉ xài 1 core thì thật là lãng phí). Trong thực tế khi xử lý một nghiệp vụ phức tạp thì việc chia công việc thành các task nhỏ để các thread khác nhau xử lý là rất hữu ích. Tuy nhiên, implement sẽ phức tạp hơn và sẽ dễ gặp một vài vấn đề mà chỉ gặp riêng đối với multithreading.

Qua phần trình bày của mình, hy vọng các bạn cảm thấy hứng thú với chủ đề multi thread. Mong nhận được ý kiến đóng góp của tất cả các bạn.
Xin cảm ơn!

Tham khảo thêm:
http://www.javatpoint.com/multithreading-in-java
http://beginnersbook.com/2013/03/multithreading-in-java/
http://crunchify.com/how-to-run-multiple-threads-concurrently-in-java-executorservice-approach/

8 thoughts on “Demo lợi ích của sử dụng multithreading trong Java

  1. Pingback: Multi thread trong Java (phần 2) Runable interface và Thread abstract class – Thạch Lê blog – chia sẻ và học hỏi

  2. Pingback: Thread interference trong Java – Java technologies

  3. Pingback: Phân biệt Runable interface và Thread abstract class » Thach Le

  4. Pingback: Thread interference trong Java » Thach Le

Leave a Reply

Your email address will not be published. Required fields are marked *