java多线程设计模式生产者消费者模式

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();
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43311669/article/details/105477857