生产者消费者模式,多线程synchrized的自我理解
作为即将毕业的应届生,多线程锁是面试高频,为了能够加深自己理解,也便自己以后能够及时复习,为此写了一篇自我理解的消费者生产者 synchrized锁的理解。
这里实现多线程之间的通信,采用了管程法,消费者生产者之间需要一个缓冲区,可以理解为一个仓库,废话不多说直接上代码;
定义一个缓冲区:含有二个属性,产品,计数器。对共享资源来说,缓冲区含有生产和消费两个方法,但按常理来说需要满足两个条件,若库存数量等于缓冲区的最大值,则生产者的线程需要等待(this.wait),消费者线程一直消费库存,并通知生产者可以继续生产 this.notifyAll()唤醒全部线程(synchrized无法指定唤醒具体线程,后续的lock锁将可以实现),同理消费者等待和生产者主动唤醒所有线程也类同。重要一点,此判断不能用if,只能用while ,因为if只会判定一次,while 每一次都判断,若多个消费者和生产者,将会造成异常,如果count为10时候,两个并发个线程都拿到10,数组越界异常(这里理解还不够充分)
class Chicken { String id; public Chicken(int id) { this.id = id; } } class SynContaier{ //容器大小 Chicken [] chickens=new Chicken[100]; Integer count = 0; ///生产者 public synchronized void push(Chicken chicken) { while (chickens.length==count) { try { System.out.println(Thread.currentThread().getName()+"------->>>>>>在等待"); this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //System.out.println("库存剩余"+count+"只鸡"); chickens[count]=chicken; count++; //通知消费者消费 this.notifyAll(); } //消费者消费产品 public Chicken pop() { synchronized(this){ while (count==0) { try { System.out.println(Thread.currentThread().getName()+"---------->在等待"); this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("库存剩余"+count+"只鸡"); Chicken chicken=chickens[count-1]; count--; this.notifyAll();() return chicken; } } }
消费者 和生产者类:
class Productor implements Runnable{ SynContaier contaier; Integer i=0; public Productor(SynContaier contaier) { this.contaier=contaier; } @Override public synchronized void run() { //锁住i 效率变低 while (true) { contaier.push(new Chicken(Thread.currentThread().getName()+"生产的第"+i)); i++; System.out.println(Thread.currentThread().getName()+"---->"+"生产了"+i+"鸡"); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } } //消费者 class Consumer implements Runnable{ SynContaier contaier; public Consumer(SynContaier contaier) { this.contaier=contaier; } @Override public synchronized void run() { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"---->消费了"+contaier.pop().id+"鸡"); } } }
测试类:
//生产消费模型 public class TestPC { public static void main(String[] args) { SynContaier contaier=new SynContaier(); for (int i = 0; i < 10; i++) { new Thread(new Productor(contaier),"生产者"+i).start(); } for (int i = 0; i < 5; i++) { new Thread(new Consumer(contaier),"消费者"+i).start(); } } }
运行结果: