Java线程之间的通信

线程之间的通信:wait(),notify(),notifyAll()

wait()——>让线程进入阻塞状态,暂停执行。一直阻塞

notify()——>唤醒线程,wait()住的线程,被唤醒。如果多个线程wait()了,唤醒其中的一个。

notifyAll()——>唤醒所有。

语法要求:必须在同步中,由同步的锁对象来调用。否则java.lang.IllegalMonitorStateException异常。

生产者消费者模型:

生产者(线程t1)负责生产产品,存入容器中(固定容量),消费者(线程t2)从容器中获取产品消费掉。
容器:
	生产者:持有资源,生产产品,存入容器中
	消费者:持有资源,消费掉产品。

容器满了:最多装8个鸡蛋
	生产者:持有资源,暂停执行——直到容器还能继续装。
		锁对象.wait()——>会让线程进入阻塞状态。暂停执行。notify(),notifyAll()
	消费者:持有资源,直接消费。。
	
容器空了:最少0个。
	生产者:持有资源,生产,存入。。
	消费者:持有资源,暂停执行——直到容器中有产品
		锁对象.wait()——>会让线程进入阻塞状态。暂停执行。notify(),notifyAll()

1、产品类:Egg()-->id
2、产生者:线程
	cpu执行,run()-->生产鸡蛋,装入容器
3、消费者:线程
	cpu执行,run()-->从容器中获取鸡蛋,吃掉(打印。。)

容器对象:

Class实现容器

数组: Egg[] arr = new Egg[8];

集合:栈,后进先出

 

同步的代码:

锁的是容器对象:

 

wait()和sleep()方法的区别:

  • 出处不同:

    • sleep()方法是Thread类中定义的。

    • wait()方法是Object类中定义的。

  • 解除阻塞的方式不同

    • sleep()是时间到,自己醒。

    • wait()方法等待被唤醒:notify(),或者是notifyAll()

  • 对锁资源的释放情况

    • sleep(),不释放,抱着不撒手

    • wait(),释放

package com.qf.demo03;

import java.util.LinkedList;

//step1:产品类:Egg,ManTou,Computer,Bread。。。
class Egg {
	private int id;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Egg() {
		super();
	}

	public Egg(int id) {
		super();
		this.id = id;
	}

	@Override
	public String toString() {
		return "Egg [id=" + id + "]";
	}
}

// step2:生产者线程:代表母鸡,下蛋
class Producer implements Runnable {
	// step5:通过构造方法,获取容器
	private LinkedList<Egg> list;
	private int id = 1;

	public Producer(LinkedList<Egg> list) {
		this.list = list;
	}

	@Override
	public void run() {
		// 母鸡下蛋,装容器
		while (true) {
			//t1
			synchronized (list) {//t1
				while(list.size() == 8){
					System.out.println("容器满了,不能再装了,母鸡应该等待。。。");
					try {
						list.wait();//正在访问的list锁对象的线程,处于了等待状态,同时释放了锁对象。。
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				// 1.生产鸡蛋
				Egg egg = new Egg(id++);//1,2
				try {
					Thread.sleep((int) (Math.random() * 1000));
//					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 2.存入容器
				list.push(egg);//1个,2个
				System.out.println(Thread.currentThread().getName() + ",母鸡下蛋:" + egg.getId());
				list.notify();//唤醒消费者线程——>如果没有线程处于wait(),那么这就是空唤醒
			}
			

		}

	}

}

// step3:消费者线程:代表吃货,吃鸡蛋
class Customer implements Runnable {
	// step5:通过构造方法,让Customer类,获取这个容器
	private LinkedList<Egg> list;

	public Customer(LinkedList<Egg> list) {
		this.list = list;
	}

	@Override
	public void run() {
		while (true) {
			//t2
			synchronized (list) {//this
				
				while(list.size() == 0){
					System.out.println("容器空的,不能吃了,吃货应该等待。。");
					try {
						list.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				// 消费鸡蛋
				Egg egg = list.pop();//8
				try {
					Thread.sleep((int) (Math.random() * 1000));
//					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("\t" + Thread.currentThread().getName() + ",消费了鸡蛋:" + egg.getId());// 8,7
				list.notify();//唤醒线程,唤醒刚刚因为list调用wait(),所处于等待的线程--->母鸡
			}
			
		}
	}

}

public class Test5ProducerAndCustomer {

	public static void main(String[] args) {
		/*
		 * 模拟生产者和消费者
		 */
		// step4:先创建一个容器
		LinkedList<Egg> list = new LinkedList<>();
		// 传入到生产者和消费者:
		Producer p = new Producer(list);
		Customer c = new Customer(list);

		Thread t1 = new Thread(p, "母鸡");
		Thread t2 = new Thread(c, "吃货");
		t1.start();
		t2.start();

	}

}

  

posted @ 2020-07-30 00:50  1769987233  阅读(144)  评论(0)    收藏  举报