生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。
生产者和消费者模式在生活当中随处可见,它描述的是协调与协作的关系。比如一个人正在准备食物(生产者),而另一个人正在吃(消费者),他们使用一个共用的桌子用于放置盘子和取走盘子,生产者准备食物,如果桌子上已经满了就等待,消费者(那个吃的)等待如果桌子空了的话。这里桌子就是一个共享的对象。
现在用代码实现这一场景。
情景一:一个消费者和一个生产者,当生产者生产一个,消费者消费一个。
首先定义资源
package com.ihujian.thread;
/**
*
* Created by Administrator on 2017/12/15.
*/
public class Resource {
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name){
if(flag){
try {
this.wait();
}catch (Exception e){
}
}
this.name = name + "----"+ count++;
System.out.println(Thread.currentThread().getName() + "。。。生产者。。"+this.name);
flag = true;
this.notify();
}
public synchronized void out(){
if(!flag){
try {
this.wait();
}catch (Exception e){
}
}
System.out.println(Thread.currentThread().getName() +"....消费者..."+this.name);
flag = false;
this.notify();
}
}
定义生产者类
package com.ihujian.thread;
/**
* Created by Administrator on 2017/12/15.
*/
public class Producer implements Runnable {
private Resource res;
public Producer(Resource res) {
this.res = res;
}
@Override
public void run() {
while (true){
res.set("+商品+");
}
}
}
定义消费者类
package com.ihujian.thread;
/**
* Created by Administrator on 2017/12/15.
*/
public class Consumer implements Runnable {
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
@Override
public void run() {
while (true){
res.out();
}
}
}
测试结果
package com.ihujian.thread;
/**
* Created by Administrator on 2017/12/15.
*/
public class Demo3 {
public static void main(String[] args) {
Resource res = new Resource();
new Thread(new Producer(res)).start();
new Thread(new Consumer(res)).start();
}
}
在这里如果是多个生产者和消费者,需要将两个方法的if改成while循环判断标记,并且讲notify()改成notifyAll()唤醒所有线程。 因为如果有多个生产者和消费者的话,使用notify()可能会唤醒己方线程,最终导致所有线程都等待
现在用jdk1.5的Lock接口来实现多消费者和多生产者的情景
定义资源类
package com.ihujian.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* jdk1.5提供了多线程的升级解决方案
* 将同步synchronized替换成现实Lock操作
* 将Object中的wait,notify,notifyAll替换了Condition对象,该对象可以通过Lock锁获取
* Created by Administrator on 2017/12/15.
*/
public class Resource2 {
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public void set(String name) throws InterruptedException {
lock.lock();
try {
while (flag) {
condition_pro.await();
}
this.name = name + "----" + count++;
System.out.println(Thread.currentThread().getName() + "。。。生产者。。" + this.name);
flag = true;
condition_con.signal();
}finally {
lock.unlock();
}
}
public void out() throws InterruptedException {
lock.lock();
try {
while (!flag) {
condition_con.await();
}
System.out.println(Thread.currentThread().getName() + "....消费者..." + this.name);
flag = false;
condition_pro.signal();
}finally {
lock.unlock();
}
}
}
生产者类
package com.ihujian.thread;
/**
* Created by Administrator on 2017/12/15.
*/
public class Producer2 implements Runnable {
private Resource2 res;
public Producer2(Resource2 res) {
this.res = res;
}
@Override
public void run() {
while (true){
try {
res.set("+商品+");
} catch (InterruptedException e) {
}
}
}
}
消费者类
package com.ihujian.thread;
/**
* Created by Administrator on 2017/12/15.
*/
public class Consumer2 implements Runnable {
private Resource2 res;
public Consumer2(Resource2 res) {
this.res = res;
}
@Override
public void run() {
while (true){
try {
res.out();
} catch (InterruptedException e) {
}
}
}
}
测试结果
package com.ihujian.thread;
/**
* Created by Administrator on 2017/12/15.
*/
public class Demo4 {
public static void main(String[] args) {
Resource2 resource2 = new Resource2();
new Thread(new Producer2(resource2)).start();
new Thread(new Producer2(resource2)).start();
new Thread(new Consumer2(resource2)).start();
new Thread(new Consumer2(resource2)).start();
}
}
网友评论