300x250 AD TOP

Thank you so much for taking the time for sharing your knowledge with me

Powered by Blogger.

Sunday, August 19, 2018

Tagged under:

Hướng dẫn Java Thread wait, notify và notifyAll

Lớp đối tượng trong java gồm có 3 hàm final cho phép thread kết nối với trạng thái khóa, mở. Những hàm này bao gồm wait(), notify(), và notifyAll(). Hôm nay chúng ta sẽ tìm hiểu về chương trình java của của các hàm wait, notify và notifyAll.

Wait, notify and notifyAll trong Java


Thread chứa những hàm trên sẽ có mội đối tượng kiểm soát, nếu không sẽ quăng lỗi java.lang.IllegalMonitorStateException.

Wait

Hàm wait gồm có 3 thành phần, thành phần đâu tiên sẽ đợi thread gọi hàm notify hoặc notifyall để đánh thức thread hiện tại. 2 thành phần còn lại sẽ được truyền vào thời gian để đánh thức thread.

Notify

Hàm notify chỉ đánh thức 1 thread đang chờ. Nếu có nhiều thread đang chờ, hàm này chỉ đánh thức 1 trong số đó. Sự lựa chọn thread đánh thức phụ thuộc vào hệ hiểu hành.

NotifyAll

Hàm notifyAll sẽ đanh thức tất cả các thraed đang chờ, thread nào được đánh thức đầu tiên sẽ tùy thuộc vào hệ điều hành.

Những hàm này có thể sử dụng để thực thi vấn đề producer consumer nơi mà consumer thread đợi một đối tượng trong Queue và producer thread thêm đối tượng vào queue và thông báo với thread đang đợi(consumer).

Dưới đây là ví dụ về nhiều thread trên cùng một đối tượng và chúng ta sẽ sử dụng hàm wait, notify và notifyall.

Message

Lớp java bean mà thread sẽ gọi hàm wait, notify, notifyall.


package com.journaldev.concurrency;

public class Message {
    private String msg;
    
    public Message(String str){
        this.msg=str;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String str) {
        this.msg=str;
    }

}


Waiter

Lớp này sẽ đợi thread gọi hàm notify để thực thi. Lưu ý rằng thread waiter sẽ có sự điều khiển đối tượng  Message của chính nó bằng cách sử dụng synchronized.

package com.journaldev.concurrency;

public class Waiter implements Runnable{
    
    private Message msg;
    
    public Waiter(Message m){
        this.msg=m;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        synchronized (msg) {
            try{
                System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
                msg.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
            //process the message now
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }

}

Notifier

Lớp này sẽ xử lý đối tượng Message và gọi hàm notify để đánh thức thead đối tượng Message đang chờ. Lưu ý rắng synchronized được sử dụng kiểm soát đổi tượng Message của chính nó.

package com.journaldev.concurrency;

public class Notifier implements Runnable {

    private Message msg;
    
    public Notifier(Message msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name+" started");
        try {
            Thread.sleep(1000);
            synchronized (msg) {
                msg.setMsg(name+" Notifier work done");
                msg.notify();
                // msg.notifyAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }

}

WaitNotifyTest

Lớp kiểm tra này sẽ được sử dụng để tạo ra nhiều thread của waiter và notifer và sau đó khởi động chúng.


package com.journaldev.concurrency;

public class WaitNotifyTest {

    public static void main(String[] args) {
        Message msg = new Message("process it");
        Waiter waiter = new Waiter(msg);
        new Thread(waiter,"waiter").start();
        
        Waiter waiter1 = new Waiter(msg);
        new Thread(waiter1, "waiter1").start();
        
        Notifier notifier = new Notifier(msg);
        new Thread(notifier, "notifier").start();
        System.out.println("All the threads are started");
    }

}
Khi chúng ta gọi hàm trên, kết quả sẽ hiển thị như bên dưới và chương trình sẽ chạy không thành công bởi vì có 2 thread đang đợi trên đối tượng Message và hàm notify chỉ đánh thức 1 trong số chúng, thread còn lại vẫn chờ để được đánh thức.

waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done
Nếu chúng ta comment hàm notify() và mở comment hàm notifyAll() thì kết quả sẽ được hiển thị như bên dưới.
Copy
waiter waiting to get notified at time:1356318917118 waiter1 waiting to get notified at time:1356318917118 All the threads are started notifier started waiter1 waiter thread got notified at time:1356318918120 waiter1 processed: notifier Notifier work done waiter waiter thread got notified at time:1356318918120 waiter processed: notifier Notifier work done
Hàm notifyAll() sẽ đánh thức 2 thread đang chờ và chương trình sẽ kết thúc sau khi thực thi.

0 comments:

Post a Comment