[Java]初识wait()、notify()方法

1.wait()、notify()、notifyAll()都是Object内的final方法,不可重写。

2.当线程执行wait()方法时,会停止执行,释放当前锁,让出cpu。

3.线程执行notify()方法时会唤醒一个等待中的线程,但不会立即释放锁。notify()唤醒线程后,被唤醒线程会接着上次的执行位置继续往下执行。

4.两个方法都要求在同步代码块中执行,也就是说当前线程已获得锁。

wait()、notify()简单应用场景:

public class T {
    //状态锁
    private Object lock;
    //条件变量
    private int now,need;
    public void produce(int num){
        //获得lock对象锁执行同步代码
        synchronized (lock){
           //当前有的不满足需要,进行等待
            while(now < need){
                try {
                    //调用wait()方法释放对象锁,让出cpu
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("我被唤醒了!");
            }
           //做其他的事情

           //调用notifyAll()唤醒所监听lock对象锁的线程
           lock.notifyAll(); 
           //同步代码块执行完后释放同步锁
        }
    }
}

为了更形象的理解等待与唤醒,现假设存在一仓库,仓库中有生产者、消费者、库存。生产者负责将物品生产出并存放至仓库,增加库存;消费者负责将物品移出仓库并消费掉。仓库存在库存上限,如果某次生产后使得物品数量大于库存上限,将不执行本次生产动作,等待消费。如果某次消费后物品数量小于零,将不执行本次消费动作,等待生产。

下面将使用wait()、notify()模拟工厂中物品的生产与消费:

抽象仓库AbstactStorage:

public interface AbstactStorage {
        //生产方法
	public abstract void produce(int num);
        //消费方法
	public abstract void consume(int num);
}

仓库类Storage:

import java.util.LinkedList;

public class Storage implements AbstactStorage{
    
        //库存上限
	private final int MAX_SIZE = 100;
        //库存
	private LinkedList<Object> list = new LinkedList<>();
	
	@Override
	public void produce(int num) {
		synchronized(list) {
			while(list.size()+num > MAX_SIZE) {
				//仓库满,等待消费
				try {
					System.out.println("库存:"+list.size()+",生产:"
                                            +num+",无法生产,等待消费");
                                        //释放list对象锁,让出cpu
					list.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			System.out.print("库存:"+list.size()+",");
			for(int i=0;i<num;i++) {
				list.add(new Object());
			}
			System.out.println("生产:"+num+",生产完毕");
                        //唤醒监听list对象锁的线程
			list.notifyAll();
		}
	}

	@Override
	public void consume(int num) {
		synchronized(list) {
			while(num > list.size()) {
				try {
					System.out.println("库存:"+list.size()+",消费:"
                                            +num+",无法消费,等待生产");
					list.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			System.out.print("库存:"+list.size()+",");
			for(int i=0;i<num;i++) {
				list.remove();
			}
			System.out.println("消费:"+num+",消费完毕");
			list.notifyAll();
		}
	}
}

生产者Producer:

public class Producer extends Thread{
	
	private int num;
	private AbstactStorage storage;
	
	public Producer(AbstactStorage storage) {
		this.storage = storage;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public void produce() {
		storage.produce(num);
	}
	
	@Override
	public void run() {
		//为了方便观察,不循环执行
		produce();
	}
}

消费者Consumer:

public class Consumer extends Thread{
	
	private int num;
	private AbstactStorage aStorage;

	public Consumer(AbstactStorage aStorage) {
		this.aStorage = aStorage;
	}
	
	public void setNum(int num) {
		this.num = num;
	}

	public void consume() {
		aStorage.consume(num);
	}
	
	@Override
	public void run() {
		consume();
	}
}

测试:

public class Demo {
	public static void main(String[] args) {
		//实例化仓库
		AbstactStorage storage = new Storage();
		//实例化消费者
		Consumer c1 = new Consumer(storage);
		Consumer c2 = new Consumer(storage);
		Consumer c3 = new Consumer(storage);
		Consumer c4 = new Consumer(storage);
		//实例化生产者
		Producer p1 = new Producer(storage);
		Producer p2 = new Producer(storage);
		Producer p3 = new Producer(storage);
		Producer p4 = new Producer(storage);
		Producer p5 = new Producer(storage);
		Producer p6 = new Producer(storage);
		Producer p7 = new Producer(storage);
		//设置消费数量
		c1.setNum(40);
		c2.setNum(40);
		c3.setNum(40);
		c4.setNum(40);
		//设置生产数量
		p1.setNum(70);
		p2.setNum(60);
		p3.setNum(50);
		p4.setNum(40);
		p5.setNum(30);
		p6.setNum(20);
		p7.setNum(10);
		//启动线程
		c1.start();
		c2.start();
		c3.start();
		c4.start();
		
		p1.start();
		p2.start();
		p3.start();
		p4.start();
		p5.start();
		p6.start();
		p7.start();
	}
}

输出:

 

参考:

https://www.cnblogs.com/moongeek/p/7631447.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值