生产者/消费者模式一种比较经典的设计模式。我们知道自定义线程的实现由两种方式,其一是集成方式,其二是实现方式,其中实现方式能多线程共享资源,而集成方式不能,而生产者/消费者模式的实现过程,正是对多线程共享资源的一次很好体现,同时也用到notify和wait两大类方法来操作线程,可以说是比较好的学习多线程知识的一次实践经历,所以本文也来总结总结。
这里实现一个生产者生产一个资源,等待消费者来消费,当资源中又数据时生产者不生产,当资源中无数据时,消费者不消费,且生产者生产一个,消费者消费一个。
1、共享资源(姓名-性别)
public class ShareResource {
private String name;
private String gender;
private boolean isEmpty = false;//共享资源是否为空
synchronized public void push(String name,String gender){
try{
while (!isEmpty){
this.wait();
}
this.name = name;
this.gender = gender;
isEmpty = false;
Thread.sleep(100);
this.notifyAll();
}catch (Exception e){
e.printStackTrace();
}
}
synchronized public void popup(){
try{
while (isEmpty){
this.wait();
}
Thread.sleep(10);
System.out.println(this.name+ "_" + this.gender);
isEmpty = true;
this.notifyAll();
}catch (Exception e){
}
}
}
这里共享资源需要注意的是方法加synchronized修饰符表示该共享资源称为线程锁,同时有线程执行线程锁的synchronized方法时,表示该线程持有该共享资源对象的锁,其它线程不持有锁,也就不能操作该共享资源对象。
而wait方法表示持有该线程锁的线程进入等待池,如果没有其它线程唤醒的话,该线程将永远不会有机会再持有该共享资源,而这里的notifyAll代表唤醒所有的线程,将线程从等待池中唤醒让其进入锁池中,但并不表示其可以立即持有线程锁。需要特别说明的是,notify和wait这两类方法是由线程锁调用的,而不是线程调用的。
2、生产者
public class Producer implements Runnable {
private ShareResource shareResource = null;
public Producer(ShareResource shareResource){
this.shareResource = shareResource;
}
@Override
public void run() {
for (int i = 0; i < 100 ; i++) {
if(i % 2 == 0){
shareResource.push("小芳","女");
}else{
shareResource.push("小明","男");
}
}
}
}
这个代码比较简单,生产者生产100个数据,奇数生产男,偶数生产女,这里通过Producer类的构造函数获得共享资源对象。
3、消费者
public class Consumer implements Runnable {
private ShareResource shareResource = null;
public Consumer(ShareResource sharedResource){
this.shareResource = sharedResource;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
shareResource.popup();
}
}
}
消费者代码就更加简单了,直接取一百次数据,同时也是通过构造函数获取共享资源对象。
以上就是生产者消费者模型实现以及一些简单说明。