Java - Vòng đời của Thread

Xin chào các bạn lập trình viên Java đang trên đường thành công! Hôm nay, chúng ta sẽ cùng nhau lặn sâu vào một trong những khía cạnh thú vị nhất của lập trình Java: vòng đời của thread. Đừng lo nếu bạn là người mới bắt đầu; tôi sẽ hướng dẫn bạn từng bước trong hành trình này, cũng như tôi đã làm cho hàng trăm sinh viên trong những năm dạy học của mình. Vậy, hãy lấy một tách cà phê (hoặc trà, nếu bạn thích), và cùng nhau bắt đầu hành trình đầy cảm hứng này nhé!

Java - Thread Life Cycle

Thread là gì?

Trước khi chúng ta nhảy vào vòng đời, hãy bắt đầu từ những điều cơ bản. Hãy tưởng tượng bạn đang ở trong một nhà bếp bận rộn. Đầu bếp đang băm rau, phụ bếp đang khuấy nồi, và đầu bếp làm bánh ngọt đang trang trí bánh. Mỗi công việc này đang diễn ra đồng thời, phải không? Trong thế giới lập trình, những nhiệm vụ này sẽ giống như các thread!

Thread là đơn vị thực thi nhỏ nhất trong một chương trình. Nó giống như một mini chương trình chạy trong chương trình chính của bạn, cho phép các phần khác nhau của mã của bạn chạy đồng thời.

Vòng đời của một Thread

Bây giờ, hãy nói về vòng đời của một thread. Giống như chúng ta con người trải qua các giai đoạn khác nhau trong cuộc sống (bé, trẻ em, teen, người lớn), thread cũng trải qua các trạng thái khác nhau trong suốt cuộc đời của nó.

Các trạng thái của vòng đời Thread trong Java

  1. New
  2. Runnable
  3. Running
  4. Blocked/Waiting
  5. Terminated

Hãy cùng phân tích chúng với một số ví dụ, nhé?

1. Trạng thái New

Khi bạn tạo một thread, nó ở trong trạng thái "New". Nó giống như một đứa trẻ sơ sinh vừa mới chào đời nhưng chưa bắt đầu bò.

Thread myThread = new Thread();

Trong ví dụ này, chúng ta đã tạo một thread mới có tên myThread, nhưng nó chưa bắt đầu chạy.

2. Trạng thái Runnable

Khi bạn gọi phương thức start() trên thread của bạn, nó vào trạng thái "Runnable". Nó sẵn sàng chạy, nhưng đang chờ lịch trình của thread chọn nó để thực thi.

myThread.start();

Bây giờ myThread giống như một đứa trẻ nhỏ, khao khát khám phá nhưng đang chờ mẹ hoặc bố đưa đi công viên.

3. Trạng thái Running

Khi lịch trình của thread chọn thread từ bộ nhớ đệm runnable, nó vào trạng thái "Running". Đây là trạng thái mà thread thực sự thực thi nhiệm vụ của mình.

public void run() {
System.out.println("Thread is running!");
}

Đây là nội dung của phương thức run(), nó xác định thread sẽ làm gì khi nó ở trong trạng thái running.

4. Trạng thái Blocked/Waiting

Đôi khi, một thread có thể cần chờ một tài nguyên hoặc một thread khác hoàn thành nhiệm vụ của nó. Trong trường hợp này, nó vào trạng thái "Blocked" hoặc "Waiting".

synchronized(object) {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Trong ví dụ này, thread đang chờ object thông báo trước khi nó có thể tiếp tục.

5. Trạng thái Terminated

Cuối cùng, khi một thread hoàn thành nhiệm vụ của mình hoặc nếu xảy ra ngoại lệ không bắt được, nó vào trạng thái "Terminated". Giống như nghỉ hưu đối với thread!

public void run() {
System.out.println("Thread is running!");
// Task của thread đã hoàn thành
}

Khi phương thức run() này hoàn thành, thread sẽ kết thúc.

Sơ đồ 流程 của vòng đời Thread trong Java

Để hình dung rõ hơn, hãy cùng nhìn vào sơ đồ:

[New] --> [Runnable] --> [Running] --> [Terminated]
^    |           |
|    |           |
|    v           v
|  [Blocked/Waiting]
|___________________|

Ví dụ Java để minh họa các trạng thái của Thread

Bây giờ, hãy öss hợp tất cả lại với một ví dụ hoàn chỉnh:

public class ThreadLifeCycleDemo implements Runnable {
public static Thread thread1;
public static ThreadLifeCycleDemo obj;

public static void main(String[] args) {
obj = new ThreadLifeCycleDemo();
thread1 = new Thread(obj);

// Thread ở trạng thái NEW
System.out.println("Trạng thái của thread1 sau khi tạo - " + thread1.getState());
thread1.start();

// Thread ở trạng thái RUNNABLE
System.out.println("Trạng thái của thread1 sau khi gọi .start() - " + thread1.getState());
}

public void run() {
Thread myThread = new Thread(new ThreadLifeCycleDemo());
// Thread ở trạng thái NEW
System.out.println("Trạng thái của myThread sau khi tạo - " + myThread.getState());
myThread.start();

// Thread ở trạng thái RUNNABLE
System.out.println("Trạng thái của myThread sau khi gọi .start() - " + myThread.getState());

try {
// di chuyển thread1 vào trạng thái chờ có thời gian
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Trạng thái của myThread sau khi gọi .sleep() - " + myThread.getState());

try {
// chờ myThread kết thúc
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Trạng thái của myThread khi nó đã kết thúc thực thi - " + myThread.getState());
}
}

Ví dụ này minh họa tất cả các trạng thái mà một thread trải qua. Khi bạn chạy chương trình này, bạn sẽ thấy đầu ra hiển thị các trạng thái khác nhau của thread khi chúng tiến hóa qua các giai đoạn của vòng đời.

Kết luận

Và thế là bạn đã có, các bạn! Chúng ta đã cùng nhau hành trình qua vòng đời của một thread Java, từ khi nó được sinh ra trong trạng thái "New" đến khi nó nghỉ hưu trong trạng thái "Terminated". Nhớ rằng, việc hiểu các trạng thái của thread rất quan trọng để viết các ứng dụng đa thread hiệu quả.

Giống như trong cuộc sống, thread trải qua các giai đoạn khác nhau, mỗi giai đoạn có những đặc điểm và thách thức riêng. Bằng cách nắm vững những khái niệm này, bạn đã tiến một bước gần hơn đến việc trở thành một chuyên gia về threading trong Java!

Hãy tiếp tục luyện tập, tiếp tục lập trình, và quan trọng nhất là hãy vui vẻ với Java! Ai biết được, có lẽ một ngày nào đó bạn sẽ là người dạy điều này cho một thế hệ lập trình viên mới. Đến gặp lại, chúc các bạn lập trình vui vẻ!

Credits: Image by storyset