Java 生产者—消费者模型技术笔记
前言程序开发中可能会碰到这种情景就是一边生产一边消耗一方面不能无限制的生产会导致溢出也不能无限制的消耗就比如飞机大战游戏敌机生产者不可能一瞬间出现很多需要控制其数量结合我们消灭敌机的速度消费者还有植物大战僵尸游戏也是这个原理1.基本概念生产者—消费者模型用于协调生产数据和使用数据的线程生产者向仓库中添加数据。消费者从仓库中取出数据。共享仓库存放数据生产者和消费者操作的是同一个仓库。仓库满时生产者等待仓库空时消费者等待。当仓库状态发生变化就通知等待的线程继续尝试工作。本文使用 List 模拟仓库最大容量为 20。privatefinalListIntegerlist;privatestaticfinalintMax20;2. 实现步骤1.先创建这样一个仓库privatefinalListIntegerlist;2.将仓库对象传给生产者和消费者3.用对象锁保护仓库由于数据共享必然存在线程安全问题要用对象锁synchronized(list){if(list.size()Max){list.add(1);list.notify();}4.如果碰到仓库满了此时生产者线程就陷入等待直到下次被唤醒继续生产消费者是如果仓库为空就停止消费进入等待直到被唤醒。if(list.size()Max){list.add(1);list.notify();}else{try{list.wait();}catch(InterruptedExceptione){Thread.currentThread().interrupt();return;}System.out.println(仓库已经生产者进入等待状态...);if(!list.isEmpty()){list.remove(0);System.out.println(消费一个仓库数量list.size());}else{try{list.wait();}catch(InterruptedExceptione){Thread.currentThread().interrupt();return;3.关键代码说明1.对象锁锁定的是共享的那个库也就是listsynchronized(list)所有线程都使用同一个 list 作为锁。同一时刻只有一个线程能够进入这些同步代码块。判断条件和实际操作必须放在一起保护。例如判断仓库未满之后不能让另一个线程插进来把仓库填满再继续添加数据。wait()等待并释放锁list.wait();当前线程进入等待同时释放 list 的锁让其他线程有机会操作仓库。线程被唤醒后需要重新获得这把锁才能从 wait() 后面继续执行。3. notifyAll()通知等待的线程list.notify();它会唤醒在 list 上等待的所有线程。这些线程随后竞争锁拿到锁后才能继续执行。调用 notifyAll() 的线程不会立即释放锁要等它退出同步代码块。4.以下为完整代码publicclassProducerimplementsRunnable{privatefinalListIntegerlist;privatestaticfinalintMax20;publicProducer(ListIntegerlist){this.listlist;}publicvoidrun(){while(true){synchronized(list){if(list.size()Max){list.add(1);list.notify();}else{try{list.wait();}catch(InterruptedExceptione){Thread.currentThread().interrupt();return;}System.out.println(仓库已经生产者进入等待状态...);}}}}}publicclassConsumerimplementsRunnable{privatefinalListIntegerlist;publicConsumer(ListIntegerlist){this.listlist;}publicvoidrun(){while(true){synchronized(list){if(!list.isEmpty()){list.remove(0);System.out.println(消费一个仓库数量list.size());}else{try{list.wait();}catch(InterruptedExceptione){Thread.currentThread().interrupt();return;}}}}}}publicclassManage{publicstaticvoidmain(String[]args){ListIntegerlistnewArrayList();ProducerproducernewProducer(list);ConsumerconsumernewConsumer(list);newThread(producer,生产者1).start();newThread(producer,生产者2).start();newThread(consumer,消费者1).start();newThread(consumer,消费者2).start();}}