0
0
Posts
TD
Truyen Duongtruyenduong0103

Tìm hiểu Java Thread notify() và wait()

Đăng vào 3 months ago

• 4 phút đọc

Chủ đề:

Java

Trong lập trình đa luồng của Java, hai phương thức quan trọng được sử dụng rộng rãi để điều khiển luồng là wait()notify(). Các phương thức này giúp các luồng giao tiếp với nhau và đồng bộ hóa hoạt động của chúng. Trong bài viết này, chúng ta sẽ khám phá chi tiết về cách hoạt động và ứng dụng của wait()notify() trong Java, đi kèm với các ví dụ cụ thể.

Khái niệm cơ bản

Phương thức wait()

Phương thức wait() là một phần của lớp Object trong Java. Khi một luồng gọi phương thức này trên một đối tượng, nó sẽ làm luồng đó ngừng thực thi và chuyển vào trạng thái chờ, cho đến khi một luồng khác gọi notify() hoặc notifyAll() trên cùng một đối tượng

Có ba biến thể của phương thức wait():

  1. wait(): Luồng hiện tại chờ đợi cho đến khi được thông báo.
  2. wait(long timeout): Luồng chờ đợi trong một khoảng thời gian xác định bằng mili giây.
  3. wait(long timeout, int nanos): Tương tự như trên nhưng thêm độ chính xác nano giây

Phương thức notify() và notifyAll()

Phương thức notify() được sử dụng để đánh thức một luồng đang chờ trên đối tượng này. Nếu có nhiều hơn một luồng đang chờ, chỉ có một luồng được chọn một cách ngẫu nhiên để được thông báo. Trong khi đó, notifyAll() sẽ đánh thức tất cả các luồng đang chờ trên đối tượng đó

Điều kiện sử dụng

Để sử dụng wait(), notify()notifyAll() một cách hiệu quả và an toàn, chúng phải được gọi từ trong một khối được đồng bộ hóa (synchronized block). Nếu không, chương trình sẽ ném ra ngoại lệ IllegalMonitorStateException

Ví dụ thực tế

Ví dụ về Producer-Consumer

Giả sử chúng ta có một tình huống sản xuất - tiêu thụ, nơi một luồng (Producer) tạo ra dữ liệu và một luồng khác (Consumer) tiêu thụ dữ liệu đó.

class Store {
    private int contents;
    private boolean available = false;

    public synchronized void put(int value) {
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        contents = value;
        available = true;
        notifyAll();
    }

    public synchronized int get() {
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        available = false;
        notifyAll();
        return contents;
    }
}

class Producer implements Runnable {
    private Store store;

    public Producer(Store store) {
        this.store = store;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            store.put(i);
        }
    }
}

class Consumer implements Runnable {
    private Store store;

    public Consumer(Store store) {
        this.store = store;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            store.get();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Store store = new Store();
        Producer producer = new Producer(store);
        Consumer consumer = new Consumer(store);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}

Trong ví dụ trên, ProducerConsumer sử dụng một đối tượng Store chung để trao đổi dữ liệu. Producer gọi put() để đặt giá trị và Consumer gọi get() để lấy giá trị. Cả hai phương thức này đều được đồng bộ hóa và sử dụng wait()notifyAll() để đảm bảo rằng ProducerConsumer không truy cập vào kho dữ liệu cùng một lúc và chờ đợi nhau một cách hợp lý

Kết luận

wait()notify() là những công cụ mạnh mẽ trong việc quản lý luồng trong Java, cho phép các luồng giao tiếp và đồng bộ hóa với nhau một cách hiệu quả. Tuy nhiên, chúng cần được sử dụng cẩn thận để tránh các vấn đề phức tạp như deadlock hoặc race conditions. Hiểu biết vững chắc về cách sử dụng các phương thức này sẽ giúp bạn xây dựng các ứng dụng đa luồng mạnh mẽ và đáng tin cậy.

Gợi ý câu hỏi phỏng vấn
Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào