一、首先定义一个产品类,定义生产和消费的方法
package com.xxchaser.Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Product {
private String brand;
private String proname;
//引入一个灯:true红色 false绿色
Boolean flag=false;
Lock lock=new ReentrantLock();
//声明一个生产者的等待队列
Condition produceCondition=lock.newCondition();
//声明一个消费者的等待队列
Condition consumerCondition=lock.newCondition();
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getProname() {
return proname;
}
public void setProname(String proname) {
this.proname = proname;
}
/**
* setProduct1 生产方法一 使用传统阻塞方法wait和notifyAll
* 生产商品
* @param brand
* @param proname
*/
public synchronized void setProduct1(String brand,String proname) {
//灯是红色,证明有商品,生产者不生产,等着消费者消费
while (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setBrand(brand);
this.setProname(proname);
System.out.println(Thread.currentThread().getName() + "生产者生产了:" + brand + proname);
flag = true;
//使用notify()会导致死锁
//notify();
//唤醒所有线程会增加一些不必要的判断,影响性能
notifyAll();
}
/**
* getProduct1 消费方法一 使用传统阻塞方法wait和notifyAll
*/
public synchronized void getProduct1() {
//灯是绿色,证明无商品,生产者开始生产,消费者等待消费
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " 消费者《消费》了:" + this.getBrand() + this.getProname());
flag = false;
//使用notify()会导致死锁
//notify();
//唤醒所有线程会增加一些不必要的判断,影响性能
notifyAll();
}
//生产商品 生产方式二
public void setProduct2(String brand,String proname)
{
lock.lock();
try {
//灯是红色,证明有商品,生产者不生产,等着消费者消费
// 这里不用if(flag)是因为多线程的时候,当生产线程被唤醒,
// 无法判断当前的flag是true还是false所以使用while来多次判断直到被唤醒时flag为true才开始生产
while (flag) {
try {
//wait();
//生产者的阻塞
produceCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setBrand(brand);
this.setProname(proname);
System.out.println(Thread.currentThread().getName()+"生产者生产了:" + brand + proname);
flag = true;
//让消费者开始消费
//notify();
consumerCondition.signal();
}
finally {
lock.unlock();
}
}
//消费商品 消费方式二
public void getProduct2()
{
lock.lock();
try {
//灯是绿色,证明无商品,生产者开始生产,消费者等待消费
// 这里不用if(!flag)是因为多线程的时候,当消费线程被唤醒,
// 无法判断当前的flag是true还是false所以使用while来多次判断直到被唤醒时flag为true才开始消费
while (!flag) {
try {
//wait();
consumerCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" 消费者《消费》了:" + this.getBrand() + this.getProname());
flag = false;
//notify();
produceCondition.signal();
}
finally {
lock.unlock();
}
}
}
二、定义生产类
package com.xxchaser.Thread;
public class ProducerThread implements Runnable {
private Product product;
public ProducerThread(Product product) {
this.product = product;
}
@Override
public void run() {
for (int i=1;i<=10;i++) {
if (i % 2 == 0) {
product.setProduct1("华为", "【手机"+i+"】by"+Thread.currentThread().getName());
//product.setProduct2("华为", "【手机"+i+"】by"+Thread.currentThread().getName());
} else {
product.setProduct1("奥玛", "【冰箱"+i+"】by"+Thread.currentThread().getName());
//product.setProduct2("奥玛", "【冰箱"+i+"】by"+Thread.currentThread().getName());
}
}
}
}
三、定义消费类
package com.xxchaser.Thread;
public class CoustomerThread implements Runnable {
private Product product;
public CoustomerThread(Product product) {
this.product = product;
}
@Override
public void run() {
for (int i=1;i<=10;i++)
{
product.getProduct1();
//product.getProduct2();
}
}
}
四、定义程序入口
package com.xxchaser.Thread;
public class TestDemo {
public static void main(String[] args) {
Product product=new Product();
ProducerThread pt=new ProducerThread(product);
CoustomerThread ct=new CoustomerThread(product);
//加入第一个生产线程
Thread t1=new Thread(pt);
t1.setName("生产者1号");
t1.start();
//加入第一个消费线程
Thread t2=new Thread(ct);
t2.setName("消费者1号");
t2.start();
//加入第二个生产线程
Thread t3=new Thread(pt);
t3.setName("生产者2号");
t3.start();
//加入第二个消费线程
Thread t4=new Thread(ct);
t4.setName("消费者2号");
t4.start();
}
}