Phân biệt Runable interface và Thread abstract class

Chào mừng các bạn đã trở lại với thachleblog. Ở bài trước mình đã giới về lợi ích của việc sử dụng multi thread trong Java. Để tạo 1 thread trong Java ta có 2 cách đó là implements Runnable interface hoặc extends Thread class. Bài viết hôm nay mình sẽ trình bày sự khác biệt giữa Runnable và Thread.

Giới thiệu

Điểm khác biệt giữa Runnable và Thread đó là Runnable là interface, Thread là abstract class. Sự khác biệt giữa abstract class và interface mình đã có 1 bài phân tích, các bạn có thể tham khảo thêm tại đây
Do đó, có sự khác biệt trong việc tạo thread bằng Runnable và Thread.

Để tạo thread bằng cách implements Runnable interface, ta thực hiện các bước:

  • Implements Runnable interface, override run() method
  • Tạo Thread object với parameter là Runnable implementation
  • Gọi start() method

Để tạo thread bằng cách extends Thread class, ta thực hiện các bước:

  • Extends Thread class, override run() method
  • Tạo thread object
  • Gọi start() method

phan biet runnable va thead class

Hình minh họa cách tạo một thread (nguồn internet)

Ví dụ

Ví dụ về tạo thread bằng extends Thread

  1. package thach.le.runnableandthread;
  2. public class ExtendThread extends Thread {
  3. @Override
  4. public void run() {
  5. System.out.println("I am extending Thread");
  6. }
  7. }

Ví dụ về tạo thread bằng implement Runable

  1. package thach.le.runnableandthread;
  2. public class ImplementRunnable implements Runnable {
  3. @Override
  4. public void run() {
  5. System.out.println("I am implementing the Runnable");
  6. }
  7. }

Tạo thread

  1. package thach.le.runnableandthread;
  2. public class TestRunnableAndThread {
  3. public static void main(String args[]) throws Exception {
  4. // Create a thread implement Runnable
  5. ImplementRunnable implementRunnable = new ImplementRunnable();
  6. Thread thread = new Thread(implementRunnable);
  7. thread.start();
  8.  
  9. // Creating a thread extend Thread
  10. ExtendThread extendThread = new ExtendThread();
  11. extendThread.start();
  12. }
  13. }

Vậy khi nào nên tạo thread bằng cách implements Runnable interface, và khi nào nên tạo thread bằng cách extends Thread class?

Chúng ta cùng phân tích lợi ích khi implements interface Runnable:

  • Nếu chúng ta implements interface Runnable, chúng ta vẫn có thể extends 1 class khác, nếu chúng ta extends Thread class chúng ta sẽ không thể extends thêm bất kì class nào vì Java không hỗ trợ đa kế thừa
  • Khi một class implements Runnable, ta nói class có khả năng “Runnable” hay còn gọi là mối quan hệ has – a, class extends Thread ta gọi class đó là “Thread” hay còn gọi mối quan hệ is – a. Trong thiết kế hướng đối tượng, thường dùng kế thừa has – a vì giúp giảm sự phụ thuộc code, code sẽ dễ test và maintain hơn.
  • Extends Thread có nghĩa là class chúng ta sẽ được kế thừa tất cả các method của Thread class, đôi khi không cần thiết, gây lãng phí bộ nhớ khi tạo thread.

Vậy khi nào ta tạo thread bằng cách extends Thread class?

Chỉ khi nào ta cần override và sử dụng các method của Thread class. Các trường hợp chỉ cần tạo thread để chạy, ta nên implements Runnable.

Bài viết của mình đến đây là hết, hẹn gặp lại các bạn ở các bài viết sau. Hy vọng bài viết giúp các bạn hiểu hơn về multi thread và có thể cân nhắc lựa chọn Runnable hoặc Thread khi apply multi thread vào trong project của mình. Rất mong nhận được đóng góp ý kiến đóng góp của tất cả các bạn.

Xin cảm ơn.

Tham khảo thêm:
http://javahungry.blogspot.com/2015/05/implements-runnable-vs-extends-thread-in-java-example.html
https://www.tutorialspoint.com//java/java_multithreading.htm

Demo lợi ích của sử dụng multi thread 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à multi thread. Multi thread 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ề multi thread 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 multi thread và concurrency, mình rất mong nhận được những góp ý từ các bạn.

Giới thiệu

Multi thread đị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, giảm thiểu thời gian thực hiện và tận dụng tốt tài nguyên của hệ thống. (Lưu ý là multi thread 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 để chạy)

Ví dụ vui

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’
Phòng mình có 3 người, 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 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

Thử với multi thread

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 multi thread 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. Trong thực tế một ứng dụng web hoặc app có thể có hàng ngàn thậm chí hàng chục ngàn request cùng một lúc, nên việc sử dụng multi thread là không thể thiếu.

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/