java线程生产者消费者模式

首先先认识一下synchronized

我们先写一个票务处理器类 用来售票 和 添加票 默认初始的票为0张

 

public class chuliqi {
	/*
	 * 票务处理器
	 * */
	private int sum=0;

	//增加票子
	public void add(){
		sum++;
		System.out.println("增加成功还有"+sum);
		
	}

	//卖票子
	public void delete(){
		sum--;
		System.out.println("卖出成功还有"+sum);
		
	}
}


接下来写个卖票的类来调用票务处理器的delete方法

 

循环20次相当于要卖出20次的票

 

public class pay implements Runnable {
	/*
	 * 卖票
	 * */

	chuliqi c;
	public pay(chuliqi c){
		this.c=c;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<20;i++)
			c.delete();
	}
}

 

 

 

在写个增加票的类来调用票务处理器的add方法

循环20次相当于要增加20次的票

 

public class product implements Runnable  {
	/*
	 * 生产票
	 * */
	chuliqi c;
	public product(chuliqi c){
		this.c=c;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<20;i++)
			c.add();
	}
}


最后写个售票机开始售票

 

 

public class shoupiaoji {

	public static void main(String[] args) {
		chuliqi c=new chuliqi();
		//目的是为了共用一份资源 也就是chuliqi
		pay py=new pay(c);
		product prt=new product(c);

		new Thread(py).start();
		new Thread(prt).start();
	}

}

运行结果 (当然是错误的 先解释下没有synchronized的情况并且怎么解决它

卖出成功还有0
增加成功还有0
增加成功还有0
卖出成功还有-1
增加成功还有1
卖出成功还有0
增加成功还有1
卖出成功还有0
卖出成功还有0
增加成功还有1
卖出成功还有-1
卖出成功还有-1
卖出成功还有-2
卖出成功还有-3
卖出成功还有-4
卖出成功还有-5
卖出成功还有-6
卖出成功还有-7
卖出成功还有-8
卖出成功还有-9
卖出成功还有-10
卖出成功还有-11
卖出成功还有-12
卖出成功还有-13
卖出成功还有-14
增加成功还有0
增加成功还有-13
增加成功还有-12
增加成功还有-11
增加成功还有-10
增加成功还有-9
增加成功还有-8
增加成功还有-7
增加成功还有-6
增加成功还有-5
增加成功还有-4
增加成功还有-3
增加成功还有-2
增加成功还有-1
增加成功还有0

看第一行的卖票,默认票为0 卖出票后面跟着应该是-1 可为什么是0?

 

因为没有加上synchronized 使得chuliqi的sum变量没有被锁住

意思可以这样理解 我增加票(add方法) sum++执行了,但是我还没来得及执行

System.out.println(增加成功还有1);

在这中间又执行了售出票(delete方法)sum--执行了,跟着也执行了 

System.out.println(减少成功还有0);

所以就会出现这种情况。总体运行如下

sum++;
sum--;
System.out.println("卖出成功还有"+sum);
System.out.println("增加成功还有"+sum);

 

 

那么我要加上synchronized锁住,这样调用的时候把你这个方法锁住等你执行完 我才释放锁,接着另外一个方法才回去执行。

加上synchronized后代码如下

 

public class chuliqi {
	/*
	 * 票务处理器
	 * */
	private int sum=0;

	//增加票子
	public synchronized void add(){
		sum++;
		System.out.println("增加成功还有"+sum);
		
	}

	//减少票子
	public synchronized void delete(){
		sum--;
		System.out.println("卖出成功还有"+sum);
		
	}
}

执行结果(还是错的,不过synchronized这个问题已经解决了

 

 

卖出成功还有-1
增加成功还有0
增加成功还有1
增加成功还有2
增加成功还有3
增加成功还有4
增加成功还有5
增加成功还有6
增加成功还有7
增加成功还有8
增加成功还有9
增加成功还有10
增加成功还有11
增加成功还有12
增加成功还有13
增加成功还有14
增加成功还有15
增加成功还有16
增加成功还有17
增加成功还有18
增加成功还有19
卖出成功还有18
卖出成功还有17
卖出成功还有16
卖出成功还有15
卖出成功还有14
卖出成功还有13
卖出成功还有12
卖出成功还有11
卖出成功还有10
卖出成功还有9
卖出成功还有8
卖出成功还有7
卖出成功还有6
卖出成功还有5
卖出成功还有4
卖出成功还有3
卖出成功还有2
卖出成功还有1
卖出成功还有0

显然可以看出synchronized问题解决了 该加1加1 该减1减1

 

但是问题就是输出结果第一行:卖出票还剩-1。 你0张票你还卖?

所以我们要增加条件 如果票等于0 那么我就wait(等待),等待你增加了票然后在notify(唤醒)我

代码如下 (PS:细心的小伙伴会发现,我wait了 但是我这个方法不是已经被锁住了吗?怎么其他方法还能调用里面的资源?其实wait之后锁会被释放,但是sleep()不行会一直锁住不会释放。 具体看点击打开链接第一个评论)

 

public class chuliqi {
	/*
	 * 票务处理器
	 * */
	private int sum=0;

	//增加票子
	public synchronized void add(){
		//如果增加的票达到满值5张 (这边可以自己设置满值)那么我先不生产票 先等待休息
		while(sum>=5){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		sum++;
		System.out.println("增加成功还有"+sum);
		this.notify();
	}

	//减少票子
	public synchronized void delete(){
		//如果票为0 那么我先休息等待 并且先解锁
		while(sum==0){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		sum--;
		System.out.println("卖出成功还有"+sum);
		this.notify();
	}
}


运行结果如下

 

 

增加成功还有1
增加成功还有2
增加成功还有3
增加成功还有4
增加成功还有5
卖出成功还有4
卖出成功还有3
增加成功还有4
增加成功还有5
卖出成功还有4
卖出成功还有3
卖出成功还有2
卖出成功还有1
卖出成功还有0
增加成功还有1
增加成功还有2
增加成功还有3
增加成功还有4
增加成功还有5
卖出成功还有4
卖出成功还有3
卖出成功还有2
卖出成功还有1
卖出成功还有0
增加成功还有1
增加成功还有2
增加成功还有3
增加成功还有4
增加成功还有5
卖出成功还有4
卖出成功还有3
卖出成功还有2
卖出成功还有1
卖出成功还有0
增加成功还有1
增加成功还有2
增加成功还有3
卖出成功还有2
卖出成功还有1
卖出成功还有0

 

 

 

具体代码例子可以去点击打开链接 下载

------------------------------------------------2018.04.05 用lock 不用synchroized--------------------------------------------

可以先到https://www.cnblogs.com/baizhanshi/p/6419268.html这里学习一下。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class chuliqi {
	/*
	 * 票务处理器
	 * */
	private int sum=0;
	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	//增加票子
	public void add(){
		//如果增加的票达到满值5张 (这边可以自己设置满值)那么我先不生产票 先等待休息
		lock.lock();
		try {
			while(sum>=5){
				try {
					condition.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			sum++;
			System.out.println("增加成功还有"+sum);
			condition.signalAll();
		}finally {
			lock.unlock();	
		}
	}

	//减少票子
	public void delete(){
		//如果票为0 那么我先休息等待 并且先解锁
		lock.lock();
		try {
			while(sum==0){
				try {
					condition.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			sum--;
			System.out.println("卖出成功还有"+sum);
			condition.signalAll();
		}finally {
			lock.unlock();	
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gentle+

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值