线程的生产者消费者模型一定是线程同步的,并且是统一工厂,这个可以用单例模式来实现,话不多说拉,直接代码演示,有可能存在不足,请留言告知!!!
1、 通过 synchronized 关键字保证线程同步来实现线程通信
工厂类,也就是容器,使用了单例模式
package cn.bzu.look.dao;
import java.util.ArrayList;
public class Warehouse {
//定义一个集合来保存商品
private ArrayList<String> arrayList = new ArrayList<>();
//定义一个Warehouse的对象,私有的,
private static Warehouse warehouse;
private Warehouse() {
}
//单例模式,得到类的对象
public static Warehouse getInstance() {
if (warehouse == null) {
warehouse = new Warehouse();
}
return warehouse;
}
public synchronized void get() {
try {
if (arrayList.size() < 3) {//
this.wait();
} else {
System.out.println("超过3个,开始购买商品"+arrayList.size());
arrayList.remove(0);
System.out.println(arrayList.size());
}
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void add() {
try {
//如果集合中的元素大于五个元素,就进入等待
if (arrayList.size() > 5) {
this.wait();
} else {
//否则就添加元素
System.out.println("不足五个,开始添加元素"+arrayList.size());
arrayList.add("hengheng");
System.out.println(arrayList.size());
}
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
生产者
package cn.bzu.look.dao;
public class Producer extends Thread {
//
private String producerName;
//得到容器的实例对象
Warehouse warehouse = Warehouse.getInstance();
public String getProducerName() {
return producerName;
}
//
public void setProducerName(String producerName) {
this.producerName = producerName;
}
public Producer(String producerName) {
super();
this.producerName = producerName;
}
@Override
public void run() {
int i = 0;
while (i<10) {
System.out.println(producerName + "开始生产产品");
warehouse.add();
try {
//睡眠200毫秒
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i++;
}
}
}
消费者
package cn.bzu.look.dao;
public class Consumer extends Thread {
Warehouse warehouse = Warehouse.getInstance();
private String consumerName;
public String getConsumerName() {
return consumerName;
}
public void setConsumerName(String consumerName) {
this.consumerName = consumerName;
}
public Consumer(String consumerName) {
super();
this.consumerName = consumerName;
}
@Override
public void run() {
int i=0;
while (i<10) {
System.out.println(consumerName + "开始购买时商品");
warehouse.get();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i++;
}
}
}
测试类
package cn.bzu.look.dao;
public class ThreadTest {
public static void main(String[] args) {
Producer pro1 = new Producer("生产者1");
Consumer con1 = new Consumer("消费者2");
pro1.start();
con1.start();
}
}
结果,結果展示的不全
消费者2开始购买时商品
生产者1开始生产产品
不足五个,开始添加元素0
1
生产者1开始生产产品
不足五个,开始添加元素1
2
消费者2开始购买时商品
生产者1开始生产产品
不足五个,开始添加元素2
3
消费者2开始购买时商品
超过3个,开始购买商品3
2
生产者1开始生产产品
不足五个,开始添加元素2
3
消费者2开始购买时商品
超过3个,开始购买商品3
2
消费者2开始购买时商品
生产者1开始生产产品
不足五个,开始添加元素2
3
消费者2开始购买时商品
超过3个,开始购买商品3
2
生产者1开始生产产品
不足五个,开始添加元素2
3
2、 ReentrantLock类加锁的线程的Condition类的await()/signal()/signalAll()来实现通信
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。
因此通常来说,线程通信的实现比较推荐使用Condition
- Condition是个接口,基本的方法就是await()和signal()方法;
- Condition依赖于Lock接口,生成一个Condition的基本代码是 lock.newCondition()
- 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await()对应Object的wait();
Condition中的signal()对应Object的notify();
Condition中的signalAll()对应Object的notifyAll()。
只改变Warehouse 类的内容,其他的类不变
public class Warehouse {
//定义一个集合来保存商品
private ArrayList<String> arrayList = new ArrayList<>();
//定义一个Warehouse的对象,私有的,
private static Warehouse warehouse;
private Lock lock;
private Condition condition;
private Warehouse(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
}
//单例模式,得到类的对象
public static Warehouse getInstance() {
if (warehouse == null) {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
warehouse = new Warehouse(lock,condition);
}
return warehouse;
}
public void get() {
lock.lock();
try {
if (arrayList.size() < 3) {
condition.await();
} else {
System.out.println("超过3个,开始购买商品" + arrayList.size());
arrayList.remove(0);
System.out.println(arrayList.size());
}
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void add() {
lock.lock();
try {
//如果集合中的元素大于五个元素,就进入等待
if (arrayList.size() > 5) {
condition.await();
} else {
//否则就添加元素
System.out.println("不足五个,开始添加元素"+arrayList.size());
arrayList.add("hengheng");
System.out.println(arrayList.size());
}
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
多线程的基础知识 https://blog.youkuaiyun.com/weixin_43610698/article/details/92800143