生产者消费者问题
该问题需要使用线程协作和线程通讯,这是一个线程同步问题,生产者和消费者共享一个资源,并且生产者和消费者之间相互依赖互为条件
问题分析:
- 对于生产者,没有生产产品之前要通知消费者等待,而生产产品之后又需马上通知消费者消费。
- 对于消费者,在消费之后,要通知生产者已经结束消费,需要生产新的产品供给消费。
- 在生产者消费者问题中只使用synchronized是不满足的,synchronized实现同步但不能实现线程之间的通信。
关于线程通信
java提供了几个方法解决线程之间通信的问题。
方法名 | 作用 |
---|---|
wait() | 表示线程一直等待,直到其他线程通知,与sleep不同,wait会释放锁 |
wait(long timeout) | 指定等待的毫秒数 |
notify() | 唤醒一个处于等待状态的线程 |
notifyAll() | 唤醒同一个对象上所用调用wait()方法的线程,优先级高的线程优先调度 |
注:以上方法都是Object类的方法,都只能在同步方法或者同步代码中使用,否则会抛出异常lllegalMonitorStateException
以下给出源码
思路流程图: 本人所写代码为老师给出题目
当面粉用完后停止生产,卖完所生产的面包后停止消费
生产者Producer类:
public class Producer implements Runnable{
private Clerk clerk;
public Producer(){}
public Producer(Clerk clerk){
super();
this.clerk=clerk;
}
@Override
public void run(){
while (true){
try{
Thread.sleep(1000);
clerk.produce();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
消费者Consumer类:
public class Consumer implements Runnable{
private Clerk clerk;
public Consumer(){}
public Consumer(Clerk clerk){
super();
this.clerk = clerk;
}
@Override
public void run(){
while (true){
try{
Thread.sleep(2000);
clerk.consume();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
店员Clerk类(操作方法类):
import java.util.LinkedList;
public class Clerk {
// 仓库容量
private final int MAX_SIZE = 10;
// 仓库存储的载体
//面粉
private LinkedList<Object> Mianlist = new LinkedList<>();
//馒头
private LinkedList<Object> ManToulist = new LinkedList<>();
public Clerk(int Mian_Counts) {
for(int i=0;i<Mian_Counts;i++) {
Mianlist.add(new Object());
}
}
public void produce() {
synchronized (Mianlist) {
while(ManToulist.size() > 20) {
System.out.println("馒头充足"+"面"+Mianlist.size());
try {
Mianlist.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (Mianlist.size() <= 0 ) {
System.out.println("无面粉无法继续生产馒头");
try {
Mianlist.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Mianlist.remove();
ManToulist.add(new Object());
System.out.println("生产一个馒头,现库存的馒头" + ManToulist.size());
Mianlist.notifyAll();
}
}
public void consume() {
synchronized (ManToulist) {
while (ManToulist.size() == 0) {
System.out.println("仓库里的馒头库存为空");
try {
ManToulist.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ManToulist.remove();
System.out.println("销售一个馒头,现库存馒头" + ManToulist.size());
ManToulist.notifyAll();
}
}
}
主线程类:
public class TestProduct {
public static void main(String[] args){
Clerk clerk = new Clerk(25);//所给面粉数量
//生产者线程
Thread producerThread = new Thread(new Producer(clerk));
//消费者线程
Thread consumerThread = new Thread(new Consumer(clerk));
producerThread.start();
consumerThread.start();
}
}
小结
对于该程序本人使用了多线程学习中学到的Runnable接口,sleep()方法,线程通信的wait()方法,notifyAll()方法等,同时也使用了LinkedList链表进行面粉和馒头的增减操作。