Thread Trong Java Là Gì Và Ưu Nhược Điểm Của Nó?
Thread (luồng) về cơ bản là một tiến trình con (sub-process). Một đơn vị xử lý nhỏ nhất của máy tính có thể thực hiện một công việc riêng biệt. Trong Java, các luồng được quản lý bởi máy ảo Java (JVM).
Multi-thread (đa luồng) là một tiến trình thực hiện nhiều luồng đồng thời. Một ứng dụng Java ngoài luồng chính có thể có các luồng khác thực thi đồng thời làm ứng dụng chạy nhanh và hiệu quả hơn.
Vòng đời của một luồng
- New : Đây là trạng thái khi luồng vừa được khởi tạo bằng phương thức khởi tạo của lớp Thread nhưng chưa được start(). Ở trạng thái này, luồng được tạo ra nhưng chưa được cấp phát tài nguyên và cũng chưa chạy. Nếu luồng đang ở trạng thái này mà ta gọi các phương thức ép buộc
stop
,resume
,suspend
… sẽ là nguyên nhân xảy ra ngoại lệ IllegalThreadStateException . - Runnable : Sau khi gọi phương thức start() thì luồng test đã được cấp phát tài nguyên và các lịch điều phối CPU cho luồng test cũng bắt đầu có hiệu lực. Ở đây, chúng ta dùng trạng thái là Runnable chứ không phải Running, vì luồng không thực sự luôn chạy mà tùy vào hệ thống mà có sự điều phối CPU khác nhau.
- Waiting: Thread chờ không giới hạn cho đến khi một luồng khác đánh thức nó.
- Deadthread vào trạng thái này khi thi hành xong tác vụ.
Ưu điểm và nhược điểm của đa luồng
1. Ưu điểm
- Nó không chặn người sử dụng vì các luồng là độc lập và bạn có thể thực hiện nhiều công việc cùng một lúc.
- Mỗi luồng có thể dùng chung và chia sẻ nguồn tài nguyên trong quá trình chạy, nhưng có thể thực hiện một cách độc lập.
- Luồng là độc lập vì vậy nó không ảnh hưởng đến luồng khác nếu ngoại lệ xảy ra trong một luồng duy nhất.
- Có thể thực hiện nhiều hoạt động với nhau để tiết kiệm thời gian. Ví dụ một ứng dụng có thể được tách thành : luồng chính chạy giao diện người dùng và các luồng phụ nhiệm gửi kết quả xử lý đến luồng chính.
2. Nhược điểm
- Càng nhiều luồng thì xử lý càng phức tạp.
- Xử lý vấn đề về tranh chấp bộ nhớ, đồng bộ dữ liệu khá phức tạp.
- Cần phát hiện tránh các luồng chết (dead lock), luồng chạy mà không làm gì trong ứng dụng cả.
Tạo ra Thread bằng cách kế thừa lớp Thread
Việc của bạn là kế thừa lớp Thread, nạp chồn phương thức run(), sau đó tạo đối tượng và gọi start để chạy thread.
class Loader extends Thread {
int i=0;
Loader(int j){
this.i = j;
}
public void run() {
for (int j = 1; j <=this.i; j++)
System.out.println("Hello " + this.i + "/" +j);
}
}
class MyClass {
public static void main(String[] args) {
Loader obj = new Loader(10);
Loader obj2 = new Loader(200);
Loader obj3 = new Loader(300);
obj.start();
obj2.start();
obj3.start();
}
}
Như bạn thấy, lớp Loader kế thừa lớp Thread và nạp chồng phương thức run(), sau khi tạo ra đối tượng, gọi run() để chạy thread.
Mọi thread trong Java đều có một độ ưu tiên, nhằm giúp hệ thống quyết định thứ tự chạy. Độ ưu tiên có mức từ 1 đến 10 và thiết lập bằng phương thức setPriority().
Tạo lớp Thread từ giao diện Runnable
Bạn cần implement giao diện Runnable và triển khai mã cho phương thức run(). Sau khi tạo đối tượng, bạn chuyển nó cho khởi tạo của lớp Thread, cuối cùng gọi start để chạy.
class Loader implements Runnable {
public void run() {
System.out.println("Hello 1");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello 2");
}
}
class MyClass {
public static void main(String[ ] args) {
Thread t = new Thread(new Loader());
t.start();
}
}
Phương thức Thread.sleep() cho phép bạn dừng lại một thread trong một khoảng thời gian.
Khi nào implements từ interface Runnable?
- Cách hay được sử dụng và được yêu thích là dùng interface Runnable, bởi vì nó không yêu cầu phải tạo một lớp kế thừa từ lớp Thread. Trong trường hợp ứng dụng thiết kế yêu cầu sử dụng đa kế thừa, chỉ có interface mới có thể giúp giải quyết vấn đề. Ngoài ra, Thread Poolrất hiểu quả và có thể được cài đặt, sử dụng rất hơn giản.
- Trong trường hợp còn lại ta có thể kế thừa từ lớp Thread.
Thứ tự ưu tiên giữa các thread
Mỗi thread có một mức ưu tiên (priority). Ưu tiên được đại diện bởi một số từ 1
đến 10
. Trong hầu hết các trường hợp, lịch trình của thread được sắp xếp theo thứ tự ưu tiên của chúng (được gọi là lập kế hoạch ưu tiên). Nhưng nó không được bảo đảm bởi vì nó phụ thuộc vào thông số kỹ thuật của JVM.
Kết luận
Chúng ta vừa mới tiếp cận kiến thức khá mới mẻ và thú vị của Java về vấn đề Đa nhiệm, cụ thể là Thread. Bài hôm nay chỉ mới là các kiến thức làm quen ban đầu, Thread còn rất nhiều kiến thức thú vị khác mà mình sẽ lần lượt trình bày ở các bài viết sắp tới nữa.