如何用代码通俗理解java中notify和wait

81 阅读2分钟

在Java中,notify()和wait()是用于线程间通信的方法。当一个线程调用对象的wait()方法时,该线程会被挂起,直到另一个线程调用该对象的notify()方法为止。下面是一个通俗易懂的例子:假设有一个面包店,有一个生产者线程和一个消费者线程。生产者线程负责生产面包,消费者线程负责消费面包。当面包库存为空时,消费者线程会进入等待状态,等待生产者线程生产面包并通知它。当生产者线程生产了面包后,会调用notify()方法通知消费者线程,消费者线程收到通知后会重新进入运行状态并消费面包。

public class BreadShop {

    private int breadCount = 0;

    public synchronized void produce() {
        while (breadCount >= 10) {
            try {
                wait(); // 库存已满,生产者线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        breadCount++;
        System.out.println("生产了1个面包,当前库存为:" + breadCount);
        notify(); // 生产完成,通知消费者线程
    }

    public synchronized void consume() {
        while (breadCount <= 0) {
            try {
                wait(); // 库存为空,消费者线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        breadCount--;
        System.out.println("消费了1个面包,当前库存为:" + breadCount);
        notify(); // 消费完成,通知生产者线程
    }

}


public class Consumer implements Runnable {

    private BreadShop breadShop;

    public Consumer(BreadShop breadShop) {
        this.breadShop = breadShop;
    }

    @Override
    public void run() {
        while (true) {
            breadShop.consume();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


public class Producer implements Runnable {

    private BreadShop breadShop;

    public Producer(BreadShop breadShop) {
        this.breadShop = breadShop;
    }

    @Override
    public void run() {
        while (true) {
            breadShop.produce();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Test {

    public static void main(String[] args) {
        BreadShop breadShop = new BreadShop();
        new Thread(new Producer(breadShop)).start();
        new Thread(new Consumer(breadShop)).start();
    }

}

另外一个例子

public class Message {

    private String content;
    private boolean available = false;

    public synchronized String getContent() {
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        available = false;
        notifyAll();
        return content;
    }

    public synchronized void setContent(String content) {
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.content = content;
        available = true;
        notifyAll();
    }

}


public class Consumer implements Runnable {

    private Message message;

    public Consumer(Message message) {
        this.message = message;
    }

    public void run() {
        String message;
        while (!(message = this.message.getContent()).equals("exit")) {
            System.out.println("Consumed " + message);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Producer implements Runnable {

    private Message message;

    public Producer(Message message) {
        this.message = message;
    }

    public void run() {
        String[] messages = {"Message 1", "Message 2", "Message 3", "Message 4"};
        for (String message : messages) {
            this.message.setContent(message);
            System.out.println("Produced " + message);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.message.setContent("exit");
    }

}


public class ThreadCommunication {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(new Producer(message)).start();
        new Thread(new Consumer(message)).start();
    }
}