version 1
/**
生产者消费者模式
1.描述资源
2.描述生产者
3.描述消费者
目前完成的程序只支持单个的生产者和消费者
但出现多个的生产者和消费者时程序会出现错误的数据
Thread-0......生产了......面包1
Thread-3....消费了....面包1
Thread-0......生产了......面包2
Thread-2......生产了......面包3
Thread-2......生产了......面包4
*/
//1.描述资源,资源属性:货品名字,货品编号;资源行为:生产货品,消费货物
class Resource{
private String name;
private int id =1;
private boolean flag = false;
//生产方法
public synchronized void set(String name){
//生产者
if(flag)
try{
wait();}catch(InterruptedException e){
}
id++;
System.out.println(Thread.currentThread().getName() + "......生产了......"+this.name);
flag = !flag;
notify();
}
//消费方法
public synchronized void out(){
if(!flag)
try{
wait();}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName() + "....消费了...." + this.name);
flag = !flag;
notify();
}
}
//2.描述生产者
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("面包");
}
}
}
//3.描述消费者
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
class ProducerConsumer{
public static void main(String[] agrs){
Resource r = new Resource();
Producer p = new Producer(r);
Producer p1 = new Producer(r);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p1);
t1.start();
t2.start();
}
}
Thread-0…生产了…面包1
Thread-3…消费了…面包1
Thread-0…生产了…面包2
Thread-2…生产了…面包3
Thread-2…生产了…面包4
问题分析:
运行程序出现错误数据
Thread-0…生产了…面包1
Thread-3…消费了…面包1
Thread-0…生产了…面包2
Thread-2…生产了…面包3
Thread-2…生产了…面包4
分析原因:原因是因为当处于等待池的线程被唤醒时,不会执行if(){}语句判断标记是否是自己该执行。
解决思路:只要让等待池中的线程被唤醒时,再次判断标记即可。
解决方法:将if(){}语句用while(){}语句替换;不会影响程序的效率,因为当标记为真时,该线程会wait(),会让出CPU资源。
version 2
/**
多生产者消费者模式
*/
//1.描述资源,资源属性:货品名字,货品编号;资源行为:生产货品,消费货物
class Resource{
private String name;
private int id =1;
private boolean flag = false;
//生产方法
public synchronized void set(String name){
//生产者
while(flag)
try{
wait();}catch(InterruptedException e){
} //t1 notify(); t2 notify();
this.name = name + id; // 生产 t1->商品1 t1->商品2 t2->商品3 数据出现了错误,再往下执行会出现没有被消费的商品
id++; //1-2-3-4
System.out.println(Thread.currentThread().getName() + "......生产了......"+this.name);
flag = !flag;
notifyAll();
}
//消费方法
public synchronized void out(){
//消费者 t3 t4
while(!flag)
try{
wait();}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName() + "....消费了...." + this.name); //消费 t3->商品1;
flag = !flag;
notifyAll();
}
}
//2.描述生产者
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("面包");
}
}
}
//3.描述消费者
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
class ProducerConsumer1{
public static void main(String[] agrs){
Resource r = new Resource();
Producer p = new Producer(r);
Producer p1 = new Producer(r);
Consumer c = new Consumer(r);
Consumer c1 = new Consumer(r);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p1);
Thread t3 = new Thread(c);
Thread t4 = new Thread(c1);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Thread-0…生产了…面包1
Thread-2…消费了…面包1
Thread-1…生产了…面包2
Thread-2…消费了…面包2
Thread-0…生产了…面包3
分析原因:
再次执行程序 上述问题解决,出现新问题程序出现死锁问题。
Thread-0…生产了…面包1
Thread-2…消费了…面包1
Thread-1…生产了…面包2
Thread-2…消费了…面包2
Thread-0…生产了…面包3
分析原因:出现新问题的原因是所有的线程都可能处于线程池,因为notify(),可能会是生产者唤醒了生产者。
解决方法:每次唤醒所有线程池的线程。
### version 3
/**
多生产者消费者模式
ProducerConsumer1程序中使用notify()方法唤醒了所有线程,程序虽然会正常执行,但是会降低效率。
学习了新的等待唤醒后,问题有了新的解决方法
思路:旧程序中不能实现唤醒对方中的一个线程,所以只能实现唤醒所有线程,效率低下。
新的同步机制可以实现一个锁有多个监听器,可以解决上述问题。
*/
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
//1.描述资源,资源属性:货品名字,货品编号;资源行为:生产货品,消费货物
class Resource{
private String name;
private int id =1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition conP = lock.newCondition();
private Condition conC = lock.newCondition();
//生产方法
public void set(String name){
lock.lock();
try{
while(flag)
try{
conP.await();}catch(InterruptedException e){
}
this.name = name + id;
id++;
System.out.println(Thread.currentThread().getName() + "......生产了......"+this.name);
flag = !flag;
conC.signal();
}finally{
lock.unlock();
}
}
//消费方法
public void out(){
lock.lock();
try{
while(!flag)
try{
conC.await();}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName() + "....消费了...." + this.name);
flag = !flag;
conP.signal();
}finally{
lock.unlock();
}
}
}
//2.描述生产者
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("面包");
}
}
}
//3.描述消费者
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
class ProducerConsumer{
public static void main(String[] agrs){
Resource r = new Resource();
Producer p = new Producer(r);
Producer p1 = new Producer(r);
Consumer c = new Consumer(r);
Consumer c1 = new Consumer(r);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p1);
Thread t3 = new Thread(c);
Thread t4 = new Thread(c1);
t1.start();
t2.start();
t3.start();
t4.start();
}
}