需求:
1 同一时间内只能有一个生产者生产
2 同一时间内只能有一个消费者消费
3 生产者生产的同时消费者不能消费
4 消费者消费的同时生产者不能生产
消费者和生产者只能有一个在工作。
----同步方法或者同步代码快
5 共享空间空时消费者不能继续消费
6 共享空间满时生产者不能继续生产
注意:
1、Wait、notify、notifyAll方法的调用必须放在同步方法和同步代码块里面
是调用“同步锁”对象的Wait、notify、notifyAll方法而不是线程对象的方法。//定义一个仓库类
public class Storage {
/*** Max_num表示仓库的最大容量
* cur_num表示当前仓库的库存
*/
static int Max_num = 100;
private int cur_num = 50;
//入库的方法
public synchronized void in(int num){
//如果当前库存加上生产者准备存放的量大于仓库的最大容量,则将该线程挂起,释放当前进程锁
try {
System.out.println(Thread.currentThread().getName() + "入库失败,仓库已溢出!请及时消费");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
cur_num += num;
System.out.println(Thread.currentThread().getName() + "入库" + num +",库存为:" + cur_num);
}
//出库的方法
public synchronized void out(int num){
//如果当前消费者的需求量大于仓库的库存,则将该线程挂起,释放当前进程锁
try {
System.out.println( Thread.currentThread().getName() + "出库失败,库存不足!请及时补货");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
cur_num -= num;
System.out.println(Thread.currentThread().getName() + "出库" + num +",库存为:" + cur_num);
}
//接着定义消费者线程类
public class Customer extends Thread{
Storage s; //根据仓库的对象实现线程同步
private int num; //当前消费者的需求量
/**
* @param name 输出当前线程名(也就是消费者名)
* @param s 传入仓库对象
* @param num 消费者的需求量
*/
public Customer(String name,Storage s,int num){
super(name);//线程名
this.s = s;
this.num = num;
}
public void run(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//调用仓库中的出库方法,将需求变量传入
s.out(num);
}
}
//还需定义一个生产者线程类
public class Producer extends Thread{
Storage s; //根据仓库的对象实现线程同步
private int num;//当生产者的生产量
/**
* @param name 输出当前线程名(也就是生产者名)
* @param s 传入仓库对象
* @param num 生产者的生产量
*/
public Producer(String name,Storage s,int num){
super(name); //线程名
this.s = s;
this.num = num;
}
public void run(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//调用仓库中的入库方法,将准备入库的数量传入
s.in(num);
}
}
//最后,创建Test类进行测试
public class Test {
public static void main(String[] args) {
//创建一个共同的仓库对象(注:这里因为是消费者线程和生产者线程要实现同步,所以只能new一个仓库对象)
Storage s = new Storage();
//创建生产者线程:
/**
* 传入线程名、对象、出入库的数量
*/
Producer p1 = new Producer("P_1", s, 50);
Producer p2 = new Producer("P_2", s, 20);
Producer p3 = new Producer("P_3", s, 30);
//创建消费者进程:
Customer c1 = new Customer("C_1", s, 60);
Customer c2 = new Customer("C_2", s, 30);
Customer c3 = new Customer("C_3", s, 60);
//启动线程
p1.start();p2.start();p3.start();
c1.start();c2.start();c3.start();
}
}