/*
* 进程通信
* 定义:一个线程完了任务以后,通知另外一个线程去完成其他的任务,这个通知以及通知的内容就称为线程通信
* 参与者: 生产者\消费者\共享对象
* 实现方法:
* wait() 等待 如果一个线程调用了wait方法,就会进入等待状态,直到被其他线程notify才继续运行;
* notify() 唤醒线程池中等待的其中一个线程
* notifyAll()
*
* 注意:
* 1. wait和notify是属于Object对象:
* 2. wait和notify必须在同步代码块和同步函数中才能执行
* 3. wait和notiry必须要有锁对象调用才能正常使用:
* 4. 生产者和消费者只共享一个对象,因此不会出现死锁的问题:
* 5. wait和notify方法必须用锁对象来调用,否则会报错.
*
* wait()和notify()方法详解
* wait() 当一个线程调用了wait()方法,就会放弃CUP执行权进入到一个以锁对象为标识符的线程池中,作用是进入线程池,但是不会唤醒其他
* notify() 当一个线程调用了notify方法,那么就会唤醒线程池中的某个线程(等待中),作用是让出CPU执行权,但是不会进入线程池;
*
*/
//生产者和消费者的共享对象,只有一个,不会出现死锁
class Product
{
String name; //产品名称
double price; //产品价格
boolean isProducted = false; //产品是否生产出来的标记
}
//生产者
class Producer extends Thread
{
Product p;
//构造函数,获取共享对象
public Producer(Product p)
{
super();
this.p = p;
}
@Override
//重写run方法
public void run() {
// TODO Auto-generated method stub
super.run();
int i =0;
while(true)
{
//共享代码块,用同一个对象来上锁,同一把锁
synchronized(p)
{
//判断是否被生产出来
if(p.isProducted)
{
p.notify();
}else{
//未被生产出来,开始生产
if(i%2 == 0)
{
p.name = "苹果";
p.price = 6.5;
}else{
p.name = "香蕉";
p.price = 2.0;
}
//生产出来,进入等待状态,等待被消费
p.isProducted = true;
System.out.println(p.name + "已经被生产出来,等待消费!" );
i++;
p.notify();
try {
p.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
//消费者
class Consumer extends Thread
{
Product p;
//构造函数,获取同一个对象来维护
public Consumer(Product p){
super();
this.p = p;
}
//重写run方法
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
int i = 0;
while(true){
synchronized(p){
//判断是否被生产s
if(p.isProducted){
System.out.println(p.name + "已经被消费,价格是:" + p.price);
p.isProducted = false;
//通知继续生产
p.notify();
}else{
//还未被生产,等待生产出来;
try {
p.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
public class Demo7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Product p = new Product();
Producer pro = new Producer(p);
Consumer con = new Consumer(p);
pro.start();
con.start();
}
}