生产者消费者问题

本文介绍了一个自定义的线程安全栈实现,通过两种不同的同步机制(wait/notify 和 Condition)确保了多线程环境下栈操作的安全性,并展示了如何通过生产者-消费者模式验证其正确性和效率。

 

 

1. 使用栈来存放数据
    1.1 把栈改造为支持线程安全
    1.2 把栈的边界操作进行处理,当栈里的数据是0的时候,访问pull的线程就会等待。 当栈里的数据是10的时候,访问push的线程就会等待
2. 提供一个生产者(Producer)线程类,生产随机大写字符压入到堆栈
3. 提供一个消费者(Consumer)线程类,从堆栈中弹出字符并打印到控制台
4. 提供一个测试类,使两个生产者和三个消费者线程同时运行,结果类似如下 

该程序主要有两部分代码:

(一)自定义的线程安全栈(如下所示)。

 用wait(), notify(), notifyAll实现

public class PCStack{
	public LinkedList<Character> stacks=new LinkedList<>();
	
	public synchronized void push(Character c) {
		try {
			Thread.sleep(100);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(stacks.size()>=10) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			};
		}else {
			stacks.addLast(c);
			this.notifyAll();
		}
		
	}
	
	public synchronized Character pull() {
		try {
			Thread.sleep(100);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(stacks.size()<=0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}else {
			this.notifyAll();
			return stacks.removeLast();
		}
	}
	
	public synchronized Character peek() {
		return stacks.getLast();
	}
}

 使用Condition对象的:await, signal,signalAll 方法实现

public class PCStack{
	public LinkedList<Character> stacks=new LinkedList<>();
	public Lock lock=new ReentrantLock();
	public Condition condition=lock.newCondition();
	public void push(Character c) {
		lock.lock();
		try {
			Thread.sleep(100);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(stacks.size()>=10) {
			try {
				condition.await();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			};
		}else {
			stacks.addLast(c);
			condition.signalAll();
		}
		lock.unlock();
		
	}
	
	public Character pull() {
		lock.lock();
		try {
			Thread.sleep(100);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if(stacks.size()<=0) {
			try {
				condition.await();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}else {
			condition.signalAll();
			Character ll=stacks.removeLast();
			lock.unlock();
			return ll;
		}
	}
	
	public synchronized Character peek() {
		return stacks.getLast();
	}
}

(二)测试类,其中有两个生产者和三个消费者(代码如下所示)。

public class P_C {
	public static void main(String[] args) {
		char[] products= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
		final PCStack mystack=new PCStack();
		for(int i=0;i<3;i++) {
			int index=i+1;
			Thread producter=new Thread() {
				public void run() {
					while(true) {
						char c=products[(int)(Math.random()*26)];
						mystack.push(c);
						System.out.println("Producter"+index+" 压入:"+c);
					}
				}
			};
			producter.start();
		}
		
		for(int i=0;i<2;i++) {
			int index=i+1;
			Thread consumer=new Thread() {
				public void run() {
					while(true) {
						Character c=mystack.pull();
						if(c!=null) {
							System.out.println("Consumer"+index+" 弹出:"+c);
						}
					}
				}
			};
			consumer.start();
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值