您的位置:首页 > 编程语言 > Java开发

java线程生产者消费者模式

2018-02-03 17:46 246 查看
首先先认识一下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张 (这边可以自己设置满值)那么我先不生产票 先等待休息
if(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 那么我先休息等待 并且先解锁
if(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
4000

卖出成功还有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 {
if(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 {
if(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();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息