Giao tiếp giữa các thread trong Java (Inter-thread communication) là một kỹ thuật cho phép các luồng đồng bộ để giao tiếp với nhau.
Giao tiếp giữa các thread là một cơ chế trong đó thread bị tạm dừng chạy trong session quan trọng của nó và một thread khác được phép xen vào (hoặc khóa) trong cùng một session quan trọng sẽ được thực hiện. Nó được thực hiện bằng các phương thức sau của lớp Object :
- wait()
- notify()
- notifyAll()
1. Phương thức wait()
Làm cho luồng hiện tại giải phóng khóa và đợi cho đến khi một thread khác gọi phương thức notify() hoặc phương thức notifyAll() cho đối tượng này, hoặc một chờ đợi khoảng thời gian xác định.
Thread hiện tại phải sở hữu monitor của đối tượng này, vì vậy nó phải được gọi từ phương thức synchronized nếu không nó sẽ xảy ra ngoại lệ.
Phương thức | Mô tả |
---|---|
public final void wait() throws InterruptedException | Chờ đợi cho đến khi đối tượng được thông báo. |
public final void wait(long timeout) throws InterruptedException | Chờ đợi một khoảng thời gian cụ thể. |
2. Phương thức notify()
Đánh thức luồng duy nhất đang chờ trên monitor của đối tượng này. Nếu có nhiều luồng nào đó đang chờ đối tượng này, một trong số chúng sẽ được đánh thức. Sự lựa chọn là độc đoán và xảy ra theo quyết định của bản cài đặt. Cú pháp:
public final void notify()
3. Phương thức notifyAll()
Đánh thức tất cả các luồng đang chờ trên monitor của đối tượng này. Cú pháp:
public final void notifyAll()
Quá trình giao tiếp giữa các thread trong java
Giải thích sơ đồ trên
- Luồng nhập vào để có được khóa.
- Khóa được chiếm bởi một luồng.
- Bây giờ luồng đi vào trạng thái chờ nếu bạn gọi phương thức wait() trên đối tượng. Nếu không, nó sẽ giải phóng khóa và thoát ra.
- Nếu bạn gọi notify() hoặc notifyAll(), luồng sẽ chuyển đến trạng thái được thông báo (trạng thái chạy được)
- Hiện luồng có sẵn để có được khóa.
- Sau khi hoàn thành nhiệm vụ, luồng sẽ giải phóng khóa và thoát khỏi trạng thái monitor của đối tượng.
Tại sao các phương thức wait(), notify() và notifyAll() được định nghĩa trong lớp Object mà không phải lớp Thread?
Đó là bởi vì chúng liên quan đến khóa và đối tượng có một khóa.
Sự khác nhau giữa wait và sleep
Hãy xem sự khác biệt quan trọng giữa phương thức wait và sleep.
wait() | sleep() |
---|---|
Phương thức wait() giải phóng khóa | Phương thức sleep() không giải phóng khóa. |
là phương thức của lớp Object | là phương thức của lớp Thread |
là phương thức non-static | là phương thức static |
nên được đánh thức bởi các phương thức notify() hoặc notifyAll() | Sleep hoàn thành sau một khoảng thời gian nhất định. |
Ví dụ về giao tiếp giữa các thread trong java
Hãy xem ví dụ đơn giản về giao tiếp giữa các thread trong java như dưới đây.
File: Test.java
class Customer { int amount = 10000; synchronized void withdraw(int amount) { System.out.println("Rút tiền..."); if (this.amount < amount) { System.out.println("Tài khoản không đủ; đợi gửi tiền..."); try { wait(); } catch (Exception e) { } } this.amount -= amount; System.out.println("Hoàn thành rút tiền!"); } synchronized void deposit(int amount) { System.out.println("Gửi tiền..."); this.amount += amount; System.out.println("Hoàn thành gửi tiền!"); notify(); } } public class Test { public static void main(String args[]) { final Customer c = new Customer(); new Thread() { public void run() { c.withdraw(15000); } }.start(); new Thread() { public void run() { c.deposit(10000); } }.start(); } }
Output:
Rút tiền... Tài khoản không đủ; đợi gửi tiền... Gửi tiền... Hoàn thành gửi tiền! Hoàn thành rút tiền!