Trong Java, một Thread đại diện cho một luồng thực thi độc lập trong chương trình, cho phép thực hiện nhiều công việc đồng thời (multithreading). Java cung cấp nhiều cách khác nhau để tạo một Thread, mỗi cách đều có các ưu điểm riêng biệt. Trong bài viết này, chúng ta sẽ xem xét các cách tạo một Thread và thảo luận về sự khác biệt giữa chúng. Cuối cùng, tôi sẽ chia sẻ quan điểm về cách tạo Thread mà tôi thích và lý do tại sao.
ThreadCách đơn giản nhất để tạo một Thread là kế thừa từ lớp Thread và ghi đè phương thức run() để định nghĩa hành vi của thread. Sau đó, bạn có thể tạo một đối tượng của lớp con và gọi phương thức start() để bắt đầu luồng thực thi.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
MyThread thread = new MyThread();
thread.start();
Trong ví dụ trên, chúng ta tạo lớp MyThread kế thừa từ Thread và định nghĩa hành vi trong phương thức run(). Phương thức start() được gọi để bắt đầu thực thi thread.
Ưu điểm:
Thread như sleep(), join(), interrupt().Nhược điểm:
Thread.RunnableMột cách khác để tạo Thread là triển khai giao diện Runnable. Bạn sẽ cần cung cấp định nghĩa cho phương thức run() và truyền một đối tượng Runnable vào đối tượng Thread để thực thi luồng.
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread is running");
}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
Trong ví dụ này, chúng ta tạo lớp MyRunnable triển khai giao diện Runnable và định nghĩa hành vi trong phương thức run(). Sau đó, chúng ta truyền đối tượng MyRunnable vào lớp Thread và gọi phương thức start().
Ưu điểm:
Runnable.Nhược điểm:
Thread, nên phải sử dụng đối tượng Thread để khởi chạy thread.Từ Java 8, với sự ra đời của biểu thức lambda, bạn có thể tạo Thread một cách gọn gàng hơn khi triển khai giao diện Runnable. Thay vì định nghĩa một lớp riêng biệt, bạn có thể truyền trực tiếp một biểu thức lambda vào Thread.
Thread thread = new Thread(() -> {
System.out.println("Thread is running");
});
thread.start();
Biểu thức lambda cho phép bạn tạo Thread một cách ngắn gọn và trực quan hơn, đặc biệt là trong những tình huống đơn giản.
Ưu điểm:
Runnable truyền thống.Nhược điểm:
Callable và FutureNếu bạn cần kết quả trả về từ thread hoặc cần xử lý ngoại lệ, giao diện Callable là lựa chọn tốt hơn so với Runnable. Callable cho phép trả về kết quả và ném ngoại lệ. Sau đó, bạn có thể sử dụng ExecutorService để quản lý thread và lấy kết quả bằng Future.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Thread result";
}
}
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new MyCallable());
String result = future.get(); // Lấy kết quả từ thread
System.out.println(result);
executor.shutdown();
Ở đây, Callable giúp bạn trả về kết quả từ thread thông qua Future. Phương thức call() thay thế run() trong Runnable và có thể ném ngoại lệ.
Ưu điểm:
Nhược điểm:
Runnable trong việc quản lý thread.ExecutorService và Future.Cách tôi thích nhất để tạo Thread trong Java là triển khai giao diện Runnable.
Runnable cho phép tôi tách biệt hành vi của thread khỏi lớp cụ thể, giúp mã nguồn dễ tái sử dụng hơn. Ngoài ra, tôi có thể kế thừa từ các lớp khác nếu cần, mà không bị giới hạn bởi việc chỉ có thể kế thừa một lớp trong Java.Runnable giúp tôi và đồng đội dễ dàng theo dõi và duy trì mã nguồn hơn, đặc biệt khi xử lý các logic phức tạp trong thread.Runnable có tính tương thích cao, dễ sử dụng và dễ kết hợp với các framework hoặc API khác trong Java. Điều này giúp tôi linh hoạt hơn khi cần tích hợp với các công cụ quản lý thread khác như ExecutorService.Tóm lại, Java cung cấp nhiều cách để tạo Thread, bao gồm kế thừa từ Thread, triển khai Runnable, sử dụng lambda, và Callable với Future. Cá nhân tôi ưa thích sử dụng Runnable vì tính linh hoạt, khả năng tái sử dụng, và tính rõ ràng mà nó mang lại trong việc phát triển phần mềm.