需求
有个工厂,去生产面包,要求每天只生产一个而且不产生浪费,也就是说每天的生产一个面包后必须消费一个面包
分析:
把工厂比作一个容器
有两个行为:生产、消费
那么在一个进程里面,这两个行为应该被视为2个线程
工厂类
- 一个生产数字
- 判断容器是否为空的标志flag
- 生产行为
- 生产行为不可被其他线程打断,因此需要加上同步
- 当容器不为空的时候,不用生产且需要进行消费
- 当生产完毕后flag应该置为true
- 消费行为
- 消费行为不可被其他线程打断,因此需要加上同步
- 当容器为空的时候应该,应该进行生产
- 消费完成后容器为空,flag应该为flase
package queue;
public class Queue {
private int n;//每天生产的面包个数
boolean flag = false;//初始状态下容器为空,没有面包
public Queue(){}
//消费的过程中不应该被打断,因此需要加上synchronized
public synchronized int getN() {
//当容器没有面包的时候,应该等待生产
if (!flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//消费的前提是容器里面有面包
System.out.println("消费:"+n);
//消费完了之后,容器里面应该是没有面包的,因此flag = false
flag = false;
//没有面包的时候应该是去唤醒那个处于等待状态的生产进程
// notifyAll();
return n;
}
//生产的过程中不应该被打断,因此需要加上synchronized
public synchronized void setN(int n) {
//当容器里面有面包的时候不用进行生产,应该是等待消费
if (flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产:"+n);
//生产完成之后flag = true
flag = true;
//此时应该唤醒消费的进程
notifyAll();
this.n = n;
}
}
生产行为的线程
package queue;
public class Producter implements Runnable{
Queue queue;
public Producter(){}
public Producter(Queue queue){
this.queue = queue;
}
@Override
public void run() {
int i = 0;
//为了效果,会一直进行生产
while(true){
queue.setN(i++);
//模拟一些打断,看的更明显
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费行为的线程
package queue;
public class Consumer implements Runnable {
Queue queue;
public Consumer(){}
public Consumer(Queue queue){this.queue = queue;}
@Override
public void run() {
while (true){
queue.getN();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试类
package queue;
public class Test {
public static void main(String[] args) {
//创建一个容器
Queue queue = new Queue();
Producter producter = new Producter(queue);
Consumer consumer = new Consumer(queue);
Thread t1 = new Thread(producter);
Thread t2 = new Thread(consumer);
t2.start();
t1.start();
}
}