之前我们说过的生产者消费者问题,当然是最简单的那种
/*
一个生产线程,一个消费线程,程序不存在安全问题
两个生产线程,两个消费线程,出现了生产两次,消费一次或生产一次消费两次的问题
出现问题的原因是:线程被唤醒之后没有回去判断标记,直接执行后边的代码
解决方式: 让线程被唤醒之后不是直接执行后边的代码,而是回去判断标记
把if改成while
把if改成while出现了死锁:原因是唤醒的是本方线程,导致所有线程全部等待
notify唤醒的是任意一个线程,不能保证唤醒的是对方线程
解决方式:把notify()改为notifyAll()
*/
代码演示的是正确的打开方式
//描述产品
class Product
{
private String name;
private int count;
private boolean flag;
//生产产品的功能
public synchronized void produce(String name)
{
while(flag)
{
try{wait();}catch(InterruptedException e){e.printStackTrace();}
}
this.name = name+"..."+count;
System.out.println(Thread.currentThread().getName()+"生产了....."+this.name);
count++;
flag = true;
notifyAll();
}
//消费产品的功能
public synchronized void consume()
{
while(!flag)
{
try{wait();}catch(InterruptedException e){e.printStackTrace();}
}
System.out.println(Thread.currentThread().getName()+"......消费了....."+name);
flag = false;
notifyAll();
}
}
//生产任务
class Producer implements Runnable
{
private Product pro;
public Producer(Product pro)
{
this.pro =pro;
}
public void run()
{
while(true)
{
pro.produce("笔记本");
}
}
}
//消费任务
class Consumer implements Runnable
{
private Product pro;
public Consumer(Product pro)
{
this.pro =pro;
}
public void run()
{
while(true)
{
pro.consume();
}
}
}
class Demo3
{
public static void main(String[] args)
{
Product pro = new Product();
Producer producer =new Producer(pro);
Consumer consumer = new Consumer(pro);
Thread t0 = new Thread(producer);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
Thread t3 = new Thread(consumer);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
我们为了解决因为wait()而导致的死锁,我们选择唤醒所有进程,但是这种方法很低效,影响代码执行效率。
在下面的文章我们选择显示锁来解决这个问题。