多线程之经典案例消费者与生产者

前言:多线程只能用thread中的start()方法调用。start()也就相当于操作系统的就绪状态

执行run()方法,相当于有了时间片,cpu可以处理你的的事情

线程同步问题一般将带有synchronized的方法封装于一个信息资源类中。唤醒方法采用柔和方式,信号量机制。有等待wait(),操作完成后要有唤醒notifyAll()。重要的是资源处理完毕一定要记得改变信号。这是很容易犯错的地方。在强调一边,记得改变信号然后再唤醒。

进行多线程问题模拟时要加入sleep(),用来模拟延迟。延迟才能体现实际生产出现的问题。

volatile关键字并不是用来处理同步问题的,请注意这一点。

 

还有一点很重要的是一般来说如果限定执行次数,因为线程切换问题,资源的实际操作次数和实际次数可能会不一样。

例如:

按原计划生产15台电脑,生产15台,消费15台,生产一台的同时消费完一台才可以进行下一次生产。但是,有可能2次时间片都是给了生产者。你选择线程循环15次,此时就是错误的。正确的方式是将10台电脑做为计数器,实际生产完一台,消费完一台,计数器才减一。另外需要有一个标志,生产标志或者消费标志。当是生产标志时才可以进行生产。

示例中也并没有加入延迟。但加入延迟并不影响。

//以下实为错误示例,不过确是解决了线程同步问题。但执行次数错误

class LxComputer{
	private static int count=0; //表示生产的个数
	private String name; //电脑名字
	private double price;//电脑价值
	public LxComputer(String name, double price) {
		this.name = name;
		this.price = price;
		count++;
	}
	@Override
	public String toString() {
		return "第"+count+"台Computer [name=" + name + ", price=" + price + "]";
	}
	
}

class ComputerResources{
	private LxComputer lxcom;
	
	public synchronized void make(){
		if(lxcom!=null){//已经生产过了,需要等待消费
			try {
				super.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}else{//没生产过,开始生产电脑
			System.out.println("开始生产电脑");
			lxcom=new LxComputer("联想电脑",555);
			System.out.println("生产电脑完毕");
			super.notifyAll();
			
		}
		
	}
	
	public synchronized void get(){
		if(lxcom==null){//还没生产,需要等待生产
			try {
				super.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
		}else{//生产过了,取走电脑
			System.out.println("正在取走电脑");
			System.out.println(lxcom.toString());
			lxcom=null;
			System.out.println("取走完毕");
			super.notifyAll();
			
		}
		
	}
	
}

class LxComProduce implements Runnable{
	private ComputerResources comre;
	public LxComProduce(ComputerResources comre){
		this.comre=comre;
	}

	@Override
	public void run() {
		for(int i=0;i<15;i++){
			System.out.println(Thread.currentThread().getName());
			this.comre.make();
		}
		
	}
	
}
class LxComConsumer implements Runnable{
	private ComputerResources crs;
	
	public LxComConsumer(ComputerResources crs){
		this.crs=crs;
	}

	@Override
	public void run() {
		for(int i=0;i<15;i++){
			System.out.println(Thread.currentThread().getName());
			this.crs.get();
		}
		
	}
	
}

public class MyComputer {
	
	public static void main(String args[]){
		ComputerResources crs=new ComputerResources() ;
		new Thread (new LxComConsumer(crs),"消费电脑").start();
		new Thread (new LxComProduce(crs),"生成电脑").start();
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值