java多线程-Producer-consumer(生产者消费者模式)
程序员文章站
2022-04-23 08:37:33
...
多线程中生产者消费者模式是非常重要的模式,如果之前的几个模式都通晓了,这个模式也就水到渠成了。废话少说,下面开始模拟.
模拟功能需要实现如下要求:
1,厨师(MakerThread)会做蛋糕(String)放在桌子(Table)上。
2,桌子太小,顶多可以放3个蛋糕。
3,桌上已经放满3个蛋糕,而厨师还要放上蛋糕的话,会等待到桌子上出现空间为止。
4,客人(EaterThread)会拿桌上的蛋糕吃。
5,桌上没有蛋糕时,客人又要拿蛋糕的话,会等待到蛋糕放到桌子上为止。
涉及的类有:
模拟功能需要实现如下要求:
1,厨师(MakerThread)会做蛋糕(String)放在桌子(Table)上。
2,桌子太小,顶多可以放3个蛋糕。
3,桌上已经放满3个蛋糕,而厨师还要放上蛋糕的话,会等待到桌子上出现空间为止。
4,客人(EaterThread)会拿桌上的蛋糕吃。
5,桌上没有蛋糕时,客人又要拿蛋糕的话,会等待到蛋糕放到桌子上为止。
涉及的类有:
package ProduceConsumerPattern; public class Table { private final String[] buffer; private int tail;//下一个put的地方 private int head; //下一个take的地方 private int count;//buffer内的蛋糕数 public Table(int count){ this.buffer = new String[count];//生成一个指定容量盛放蛋糕的容器 this.head = 0; //设置下一个放蛋糕的数组索引值 this.tail = 0; //设置下一个拿蛋糕的数组索引值 this.count = 0; //设置容器内含有的蛋糕的数量 } /* * 放置蛋糕 */ public synchronized void put(String cake)throws InterruptedException{ System.out.println(Thread.currentThread().getName() + "puts:" + cake); while(count >= buffer.length){//如果容器上有大于等于3个蛋糕的话线程进入Table的线程等待区 wait(); } buffer[tail] = cake;//如果容器里没有满的话,把蛋糕放进容器里 tail = (tail+1) % buffer.length; count++;//增加蛋糕的数量 notifyAll(); } //获取蛋糕 public synchronized String take() throws InterruptedException{ while(count<=0){ wait(); } String cake = buffer[head]; head = (head+1) % buffer.length; count--; notifyAll(); System.out.println(Thread.currentThread().getName() + "takes:" + cake); return cake; } } package ProduceConsumerPattern; import java.util.Random; public class MakerThread extends Thread{ private final Random random; private final Table table; private static int id = 0;//蛋糕的流水号(每个线程都一样) public MakerThread(String name,Table table,long seed){ super(name); this.table = table; this.random = new Random(seed); } public void run(){ try { while(true){ Thread.sleep(random.nextInt(1000)); String cake = "[Cake No."+ nextId() + "by " + getName(); table.put(cake); } } catch (InterruptedException e) { e.printStackTrace(); } } public static synchronized int nextId(){ return id++; } } package ProduceConsumerPattern; import java.util.Random; public class EaterThread extends Thread{ private final Random random; private final Table table; public EaterThread(String name,Table table, long seed){ super(name); this.table = table; this.random = new Random(seed); } public void run(){ try { while(true){ String cake = table.take(); Thread.sleep(random.nextInt(1000)); } } catch (Exception e) { // TODO: handle exception } } } package ProduceConsumerPattern; public class Main { public static void main(String[] args) { Table table = new Table(3); new MakerThread("MakerThread-1",table,31415).start(); new MakerThread("MakerThread-2",table,92653).start(); new MakerThread("MakerThread-3",table,58979).start(); new EaterThread("EaterThread-1",table,32384).start(); new EaterThread("MakerThread-2",table,62643).start(); new EaterThread("EaterThread-3",table,38327).start(); } }