题目:
生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产; 如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
分析问题:
- 1.使用多线程:生产者和消费者
- 2.共享数据:产品的数量
- 3.线程的通信:存在生产者和消费者的通信
这里可能出现两个问题:
- 生产者比消费者快时,消费者会漏掉一些数据没有取到。
- 消费者比生产者快时,消费者会取相同的数据。
生产者
class Producer implements Runnable{
public Producer(Clerk clerk) {
// TODO Auto-generated constructor stub
this.clerk = clerk;
}
Clerk clerk;
// 生产产品
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Producing");
while (true) {
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.addProduct();
}
}
}
消费者
class Customer implements Runnable{
Clerk clerk;
public Customer(Clerk clerk) {
// TODO Auto-generated constructor stub
this.clerk = clerk;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Consuming");
while (true) {
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("********");
clerk.consumeProduct();
System.out.println("********");
}
}
}
店员
class Clerk {
// 产品
int product;
// 生产产品的方法
public synchronized void addProduct() {
if (product >= 20) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
product++;
System.out.println(Thread.currentThread().getName() + "生产了第" + product + "个产品");
notifyAll();
}
}
// 消费产品的方法
public synchronized void consumeProduct(){
// 消费产品
if(product<=0){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
product--;
System.out.println(Thread.currentThread().getName()+"消费了第"+product+"个产品");
notifyAll();
}
}
}
main方法
public class TestProduce {
public static void main(String[] args) {
Clerk clerk = new Clerk();
// 创建生产者和消费者对象
Producer p1 = new Producer(clerk);
Customer c1 = new Customer(clerk);
// 创建生产者线程
Thread t1 = new Thread(p1);
Thread t3 = new Thread(p1);
// 创建消费者线程
Thread t2 = new Thread(c1);
t1.setName("生产者1");
t3.setName("生产者2");
t2.setName("消费者");
t1.start();
t2.start();
t3.start();
}
}
实现多线程需要重写run()方法,run()中存放的是需要执行的代码,也就是多线程实现的代码,而开启一个多线程需要调用的start()方法,而不是run()方法。
有关多线程看到一个比较详细有关线程的博客,就保留了下来,方便以后查找
https://blog.youkuaiyun.com/hp_yangpeng/article/details/79406099