线程互斥就是我们前面所学到的临界区的加锁机制就是使用synchronized和关键字volatile进行同步操作,但是线程之间仅仅通过互斥还不能很号的工作我们还需要线程之间的协作,就是我们今天所要探究的生产者和消费者.
生产者和消费者模型相信大家在大学的操作系统一门课中已经有所接触;具体的意思就是有一个公共的区域我们作为商品池,生产着呢就往这个池子放生产出来的商品,当这个池子满的时候生产者就不能在往里面放东西了,那么他现在有俩个选择,一个就是进入阻塞队列中,等待消费者消费池子中的商品,池子中的商品被消费之后他才可以进行商品的继续 放进去,还有一个就是他在池子满的时候丢弃生产出来的商品.那么 相对应的就是消费者了,消费者呢在池子中有商品的时候可以取池子中的商品 进行消费,当池子中没有商品的时候他就只有一手准备了就是,等待池子中有商品 了在进行商品的消费.
现在我们通过一个例子来说明下生产者和消费者:比如有一个篮子,他里面存放鸡蛋,当有鸡蛋的时候呢生产者等待或者丢弃,知道消费者把鸡蛋拿走,他才能在篮子里放新的鸡蛋,消费者呢就是当篮子里有鸡蛋的时候才去取篮子中的鸡蛋直到篮子没有鸡蛋了就等待,当生产者重新放入鸡蛋在篮子里他就取鸡蛋消费.好了我们看看我们的代码实现
首先是存放的鸡蛋类:
/** * Created by luyangli on 16-6-21. */ public class Egg { private String egg; public String getEgg() { return egg; } public void setEgg(String egg) { this.egg = egg; } public Egg(String egg) { this.egg = egg; } }可以看到什么都没有做,只是一个成员变量,其实这个变量我们也可以不用设置,就键一个空的类就可以
然后呢就是我们的篮子:/** * Created by luyangli on 16-6-21. */ public class Plate { public static void main(String[] args) { List<Egg> eggList = new ArrayList<Egg>(); //注意这个就是篮子啦 Provider provider = new Provider(eggList); //生产者 Consumer consumer = new Consumer(eggList); //消费者 for (int i=0; i<10; i++) { //分别启动10个线程 new Thread(provider).start(); new Thread(consumer).start(); } } }这个就是我们的篮子,其实我们的篮子就是一个列表,其实按照我们所说的,只要一个长度的列表就OK啦,当有鸡蛋的时候生产者等待,就是说有一个鸡蛋的收生产者也是等待状态,消费者消费,当没有鸡蛋的时候消费者等待.在这里我们需要构造一个消费者和一个生产者实例,我们可以看到消费者和生产者是使用同一个篮子,这样的话就不会放在别的篮子里来了.
然后就是我们的消费者和生产者:
/** * Created by luyangli on 16-6-21. */ public class Provider implements Runnable { private List<Egg> eggList; public Provider(List<Egg> eggList) { this.eggList = eggList; } private synchronized void putEgg(){ while (eggList.size() > 0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } Egg egg = new Egg("egg"); eggList.add(egg); System.out.println("加入了鸡蛋"); notify(); } @Override public void run() { putEgg(); } }生产者就是在篮子有鸡蛋的时候呢,等待,当没有鸡蛋的时候就添加鸡蛋,唤醒消费者消费
/** * Created by luyangli on 16-6-21. */ public class Consumer implements Runnable{ private List<Egg> eggList; public Consumer(List<Egg> eggList) { this.eggList = eggList; } private synchronized void getEgg(){ while (eggList.size() <= 0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } Egg egg = eggList.get(0); eggList.clear(); notify(); System.out.println("拿到了鸡蛋"); } @Override public void run() { getEgg(); } }消费者呢就是在篮子没有鸡蛋的时候等待,要是篮子有鸡蛋的话就消费然后唤醒生产者添加鸡蛋.
我们想要的结果是这样的:当篮子有鸡蛋的时候就通知消费者进行消费,这个时候生产者是等待的状态,篮子没有鸡蛋的时候是生产者添加鸡蛋,消费者是等待状态的,我们来看你一下执行的效果是不是我们所期望的: 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 加入了鸡蛋 拿到了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋
看起来这个结果是我们索要的,但是我们要是执行多次呢: 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋 加入了鸡蛋 拿到了鸡蛋
这个怎么才有8个线程在操作一样,其他的两个线程呢,这个问题先记这,有没有大神给我指点下迷津呢,ganjibujin