消费者线程
package com.bjsxt.commu5;
/**
* 消费者线程
*/
public class ConsumeRunnable implements Runnable {
//private Product product = new Product();
private Product product;
private Object obj = new Object();
public ConsumeRunnable() {
}
public ConsumeRunnable(Product product) {
this.product = product;
}
public void setProduct(Product product) {
this.product = product;
}
@Override
public void run() {
while(true){
product.consume();
}
}
}
生产者线程
package com.bjsxt.commu5;
/**
* 生产者线程
*/
public class ProduceRunnable implements Runnable {
//private Product product = new Product();
private Product product;
public ProduceRunnable() {
}
public ProduceRunnable(Product product) {
this.product = product;
}
public void setProduct(Product product) {
this.product = product;
}
@Override
public void run() {
int i = 0;
while(true){
product.produce(i);
i++;
}
}
}
产品
package com.bjsxt.commu5;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 商品类
*/
public class Product {
private String name;//名称 馒头 玉米饼
private String color;//颜色 白色 黄色
boolean flag = false;//默认没有商品
private Lock lock = new ReentrantLock();
private Condition produceCondition = lock.newCondition();
private Condition consumeCondition = lock.newCondition();
public Product() {
}
public Product(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
/**
* 生产一个商品
*/
public void produce(int i){//this
lock.lock();
try{
//1.如果已经有商品,就等待
if(flag){
try {
//this.wait();
produceCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2. 生产商品并输出
if(i%2 ==0 ){
//product.setName("馒头");
this.name = "馒头";
try {
Thread.sleep(10); //只释放cpu不释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
//product.setColor("白色");
this.color = "白色";
}else{
//product.setName("玉米饼");
this.name = "玉米饼";
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//product.setColor("黄色");
this.color = "黄色";
}
System.out.println("生产者生产一个商品:"+name+" "+color);
//3.改变商品有无的状态:有商品了
this.flag = true;
//4.通知消费
//this.notify();//随机的唤醒一个线程(目前只有两个,被唤醒的肯定是消费者)
consumeCondition.signal();
}finally {
lock.unlock();
}
}
/**
* 消费一个商品
*/
public void consume(){//this
lock.lock();
try{
//1.如果没有商品,就等待
if(!flag){
try {
//this.wait(); //让出了cpu,也让出了锁
//wait();
consumeCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2.消费商品
System.out.println("消费者消费一个商品:"+name+" "+color);
//3.改变商品的有无状态:无
this.flag = false;
//4.通知生产者生产
//this.notifyAll();//唤醒所有等待的线程(目前所有等待的线程只有一个,就是消费者)
produceCondition.signalAll();
}finally {
lock.unlock();
}
}
}
main
package com.bjsxt.commu5;
public class Test {
public static void main(String[] args) {
Product product = new Product();
//创建线程对象
Runnable runnable1 = new ProduceRunnable(product);
Thread thread1 = new Thread(runnable1);
ConsumeRunnable runnable2 = new ConsumeRunnable();
runnable2.setProduct(product);
Thread thread2 = new Thread(runnable2);
//启动线程
thread1.start();
thread2.start();
}
}
遇到的问题及解决方案:
- 问题1:生产和消费没有交互
- 解决:线程通信…
- 问题2:和商品没有关系
- 解决:定义一个商品类
- 问题3:生产者可以交替的生产,但是消费者消费的一直是null
- 解决:保证生产者生产和消费者消费的是同一个商品
- 问题4:出现了白色的玉米饼和黄色的馒头
- 解决:需要进行线程同步
- 问题1:生产和消费没有交互
- 解决:线程通信…
- 使用从Object类继承的wait() notify() notifyAll()方法实现通信
- 注意事项: 必须调用同步监视器的wait() notify() notifyAll()方法
-
product.wait();
-
product.notify();
-
product.notifyAll();