1. Tiến trình (Process) và luồng (Thread) là gì?
Tiến trình (Process) là một chương trình máy tính đang được thực thi. Một phần mềm đang chạy thì có thể có nhiều tiến trình. Ví dụ, phần mềm Zalo đang chạy có nhiều tiến trình, mỗi tiến trình được hệ điều hành gán cho một PID (Process ID) để quản lý.
Một tiến trình (Process) thì có thể bao gồm một hoặc nhiều luồng (Thread). Thread là một chuỗi lệnh nhỏ nhất có thể được hệ điều hành quản lý độc lập và đưa vào CPU để xử lý nhằm thực hiện một công việc nhất định. Để hiểu rõ hơn về Process và Thread, chúng ta cùng xem mô hình thực thi (execute) một chương trình ở hình bên dưới.
Một chương trình máy tính thường được lưu trong ổ đĩa (Disk) gồm rất nhiều lệnh (instruction). Khi người dùng chạy chương trình, các lệnh của chương trình sẽ được lưu trên RAM để gửi cho CPU xử lý. Lúc này, một tiến trình (Process) được hình thành. Trên RAM có thể lưu trữ lệnh của nhiều tiến trình khác nhau. Mỗi tiến trình thì lại gồm nhiều luồng (Thread) khác nhau.
Vậy luồng (Thread) nào sẽ được đưa vào CPU để thực thi trước? Việc này phụ thuộc vào bộ lập lịch (Scheduler) của hệ điều hành hoặc của JVM quyết định. Mỗi luồng (Thread) sẽ được hệ điều hành quản lý và đánh một độ ưu tiên cho các Thread. Dựa vào độ ưu tiên của Thread và khả năng xử lý của CPU (số nhân, số luồng) mà hệ điều hành sẽ gửi các Thread đến CPU để xử lý.
Process và Thread bao gồm những gì?
Mỗi tiến trình (Process) bao gồm các lệnh (code), dữ liệu (data), tập tin (file) riêng. Mỗi tiến trình thường thực thi độc lập với nhau, việc giao tiếp giữa các tiến trình rất hạn chế.
Trong một tiến trình, có thể có nhiều Thread. Mỗi Thread có bộ đếm chương trình (counter), các thanh ghi (registers) và vùng nhớ stack riêng. Các Thread trong cùng một tiến trình có thể chia sẻ nhau code, data, file trong tiến trình. Các Thread trong cùng một tiến trình cũng có thể thường xuyên giao tiếp với nhau để thực hiện công việc của Process.
Main Thread trong Java
Khi một chương trình Java khởi chạy, một Main Thread được tạo ra. Main Thread sẽ đi tìm hàm main()
để thực thi. Nếu không tìm thấy hàm main()
thì chương trình sẽ bị báo lỗi. Main Thread có thể khởi chạy các Thread khác trong hàm main()
.
2. Vòng đời của luồng (Thread)
Thread trong Java có các trạng thái (state): new, runnable, blocked, waiting, timed_waiting, terminated.
1. Trạng thái new: Khi Thread mới được tạo, nó có trạng thái là new. Lúc này, Thread chưa được thực thi lệnh nào.
2. Trạng thái runnable: Khi một Thread đang chạy hoặc có thể sẵn sàng chạy bất cứ lúc nào tùy vào bộ lập lịch (Scheduler) của hệ điều hành thì trạng thái là runnable.
3. Trạng thái blocked/waiting: Khi một Thread tạm thời không hoạt động thì Thread có thể ở trạng thái blocked hoặc waiting.
4. Trạng thái timed_waiting: Một Thread có thể được bộ lập lịch (Scheduler) của hệ điều hành thiết lập một thời gian chờ để được thực thi.
5. Trạng thái terminated: Một Thread có thể được kết thúc vì nó đã thực thi xong hoặc gặp một ngoại lệ (exception) nào đó.
3. Cách tạo Thread trong Java
Có 2 cách để tạo ra Thread trong Java là:
- Kế thừa lớp java.lang.Thread
- Implement từ interface java.lang.Runnable
3.1. Tạo Thread với kế thừa lớp Thread trong Java
Lớp Thread cung cấp các hàm khởi tạo và các phương thức để tạo và thực hiện các hoạt động trên một Thread. Lớp Thread kế thừa từ interface Runnable.
Lớp Thread cung cấp các hàm khởi tạo:
Thread()
Thread(String name)
Thread(Runnable r)
Thread(Runnable r, String name)
Các phương thức thường dùng của lớp Thread là:
public void run()
: thực hiện các lệnh cho Thread.public void start()
: bắt đầu thực thi Thread. JVM gọi hàmrun()
của Thread.public void sleep(long miliseconds)
: làm cho Thread chuyển qua trạng thái sleep (tạm thời dừng thực thi) trong một khoảng thời gian milliseconds.public void join()
: chờ một Thread kết thúc.public void join(long miliseconds)
: chờ một Thread kết thúc trong khoảng thời gian là miliseconds.public int getPriority()
: trả về độ ưu tiên (priority) của Thread.public int setPriority(int priority)
: thay đổi độ ưu tiên (priority) của Thread.public String getName()
: trả về tên của Thread.public void setName(String name)
: thay đổi tên của Thread.public Thread currentThread()
: trả về Thread đang thực thi.public int getId()
: trả về ID của Thread.public Thread.State getState()
: trả về trạng thái của Thread, có kiểu dữ liệu enum State là:
public enum State {
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;}
public boolean isAlive()
: kiểm tra Thread còn sống không.public void yield()
: làm Thread đang thực thi tạm ngưng và cho phép Thread khác thực thi.public void suspend()
: làm Thread tạm ngưng.public void resume()
: tiếp tục thực thi Thread đã tạm ngưng.public void stop()
: dừng Thread.public boolean isDaemon()
: kiểm tra Thread có phải là Daemon Thread hay không.public void setDaemon(boolean b)
: đánh dấu Thread là Daemon hoặc User Thread. Nếu booleanb
là true thì Thread là Daemon Thread, ngược lại là User Thread.public void interrupt()
: ngắt (interrupt) thực thi Thread.public boolean isInterrupted()
: kiểm tra Thread đã bị ngắt (interrupted) chưa.public static boolean interrupted()
: kiểm tra Thread hiện tại đã bị ngắt (interrupted) chưa.
Ví dụ tạo Thread với kế thừa lớp Thread
class MyThread extends Thread{
@Override
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
MyThread t1=new MyThread();
t1.start();
}
}
Kết quả
thread is running...
3.2. Tạo Thread với implement từ interface Runnable trong Java
Interface Runnable chỉ có một hàm run()
để thực hiện các lệnh cho Thread. Các Thread được tạo ra cần định nghĩa lại hàm run()
này.
Để chạy Thread kế thừa từ interface Runnable thì cần sử dụng hàm khởi tạo của lớp Thread. Sau đó, chúng ta gọi hàm start()
để bắt đầu một Thread. Lúc này, Thread cũng sẽ tự động gọi hàm run()
được định nghĩa lại trong Thread kế thừa từ interface Runnable để thực hiện các công việc cần thiết.
class MyThread implements Runnable{
@Override
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
MyThread m1=new MyThread();
//Sử dụng hàm khởi tạo Thread(Runnable r)
Thread t1 =new Thread(m1);
t1.start();
}
}
Kết quả
thread is running...