消费者与生产者的问题是计算机中常见的问题,是在java多线程经典问题
1.java多线程实现
wait() / notify()方法
wait() / nofity()方法是基类Object的两个方法:
- wait()方法:当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等等状态,让其他线程执行。
- notify()方法:当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
import java.util.LinkedList;
public class produceAndCustomer {
//最大商品数
private final int MAX_LIST_SIZE = 100;
//商品集合存放处,需要频繁的插入与删除,使用LinkedList。
private LinkedList<Object> itemList = new LinkedList<>();
//生产者生产商品
//生产者在商品集合满时,不许生产
public void produce(String produceName) {
synchronized (itemList) {
while (itemList.size() == MAX_LIST_SIZE) {
System.out.println("厂库已满: 暂时不能执行生产任务!");
try {
//当商品集合长度等于最大长度,则生产者停止生产
itemList.wait();
} catch (InterruptedException e) {
System.out.println();
e.printStackTrace();
}
}
//生产未满足厂库总容量
//生产商品
itemList.add(new Object());
System.out.println("生产者生产了一个商品,厂库现容量为:"+itemList.size());
//生产出商品,唤醒消费者消费
itemList.notifyAll();
}
}
//消费者消费商品
//消费者在商品集合为空时,不许消费
public void customer(String customerName) {
synchronized (itemList) {
while (itemList.size()==0){
System.out.println("厂库为空: 暂时不能执行消费任务!");
try {
//厂库为空时,消费者不能够消费,停止线程
itemList.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//厂库不为空,能够消费
itemList.removeFirst();
System.out.println("消费者消费了一个商品,厂库现容量为:"+itemList.size());
//消费了商品,唤醒生产者生产
itemList.notifyAll();
}
}
//属性的get和set操作
public LinkedList<Object> getItemList() {
return itemList;
}
public void setItemList(LinkedList<Object> itemList) {
this.itemList = itemList;
}
public int getMAX_LIST_SIZE() {
return MAX_LIST_SIZE;
}
}
测试方法:
public class Test {
//消费者与生产者的测试方法
public static void main(String[] args) {
produceAndCustomer produceAndCustomer = new produceAndCustomer();
//定义8个生产者,执行8次生产
for (int i = 0; i < 8; i++) {
int num = i;
//使用匿名内部类的方式去实现
new Thread(new Runnable() {
public void run() {
produceAndCustomer.produce(String.format("生产者%d", num));
}
}).start();
}
//定义4个消费者,执行4次消费
for(int i=1;i<4;i++)
{
int num = i;
//使用匿名内部类的方式去实现
new Thread(new Runnable() {
public void run() {
produceAndCustomer.customer(String.format("生产者%d", num));
}
}).start();
}
}
}
3.执行结果
生产者生产了一个商品,厂库现容量为:1
消费者消费了一个商品,厂库现容量为:0
生产者生产了一个商品,厂库现容量为:1
生产者生产了一个商品,厂库现容量为:2
生产者生产了一个商品,厂库现容量为:3
生产者生产了一个商品,厂库现容量为:4
消费者消费了一个商品,厂库现容量为:3
消费者消费了一个商品,厂库现容量为:2
生产者生产了一个商品,厂库现容量为:3
生产者生产了一个商品,厂库现容量为:4
生产者生产了一个商品,厂库现容量为:5
还有另外一种锁的方式
- await() / signal()方法
代码类似于上述方式,是wait(),和notify()方法的一种变形。小伙伴们可以自己尝试一下