java中使用阻塞队列解决生产者消费者问题

来源:互联网 发布:淘宝裸根月季苗 编辑:程序博客网 时间:2024/06/06 19:46

java语言中提供了blockingQueue阻塞队列以及几种实现:
blockingQueue接口

在解决多线程生产者,消费者问题的时候,可以使用阻塞队列来代替java同步原语wati()和notify()以及sychronized。简化编程模型。

下面使用linkedBlockingQueue来简化生产者消费者问题[1]。

问题:有一台机器有三个任务,一个制作toast,一个抹黄油,一个涂果酱,还有一个消费toast的人,总共有四个任务,使用队列解决这四个任务之间的协同?
解决方法描述如下图:
使用阻塞队列的任务传递过程

  1. make线程制作toast之后put到dryQueue
  2. butterer线程从dryQueue队列take获得toast,处理之后放入butteredQueue队列
  3. jammer线程从butteredQueue队列take获得toast,处理之后放入finnishedQueue队列

阻塞队列take方法在队列为空时阻塞,直到队列中有元素为止。使用阻塞队列处理的好处就是:在程序中可以不使用任何显示的同步以及wait()/notify()等方法。

1,toast类
使用枚举类型描述toast的状态

/** * 枚举类 * @author lecky * */public class Toast {    public  enum Status {DRY,BUTTER,JAMMED}    private Status status = Status.DRY;    private final int id;    public Toast(int id) {        super();        this.id = id;    }    public void butter(){        status = Status.BUTTER;    }    public void jammer(){        status = Status.JAMMED;    }    public int getId() {        return id;    }    public Status getStatus() {        return status;    }    @Override    public String toString() {        return "Toast [status=" + status + ", id=" + id + "]";    }}

2,Toaster类

import java.util.concurrent.BlockingQueue;/** * 制作面包线程 * 只与dryQueue阻塞队列交互,做完面包之后就交给dryQueue队列 * @author lecky * */public class Toaster implements Runnable{    private BlockingQueue<Toast> dryQueue;    private int count=0;    public Toaster(BlockingQueue<Toast> dryQueue) {        this.dryQueue = dryQueue;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                Thread.sleep(1000);//制作toast                Toast t = new Toast(++count);                dryQueue.put(t);                System.out.println("toaster make the toast!"+t);            }        } catch (InterruptedException e) {            System.out.println("Toaster InterruptedException");        }        System.out.println("Toaster OK!");    }}

3,Butterer类

import java.util.concurrent.BlockingQueue;/** * 抹黄油线程 * 从dryQueue队列获得任务,并抹黄油之后交给butterQueue队列 * @author lecky * */public class Butterer implements Runnable{    private BlockingQueue<Toast> dryQueue;    private BlockingQueue<Toast> butterQueue;    public Butterer(BlockingQueue<Toast> dryQueue,            BlockingQueue<Toast> butterQueue) {        this.dryQueue = dryQueue;        this.butterQueue = butterQueue;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                Toast t = dryQueue.take();                System.out.println("Butterer Take The Toast and buttering........"+t);                t.butter();                Thread.sleep(500);//butterer过程                butterQueue.put(t);            }        } catch (InterruptedException e) {            System.out.println("Butter InterruptedException");        }        System.out.println("butterer Off!");    }}

4,Jammer类

import java.util.concurrent.BlockingQueue;/** * 涂果酱任务 * 从butterQueue队列获取任务并涂上果酱,交给finishedQueue * @author lecky * */public class Jammer implements Runnable{    private BlockingQueue<Toast> butterQueue;    private BlockingQueue<Toast> finishedQueue;    public Jammer(BlockingQueue<Toast> butterQueue,            BlockingQueue<Toast> finishedQueue) {        this.butterQueue = butterQueue;        this.finishedQueue = finishedQueue;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                Toast t = butterQueue.take();                System.out.println("jammer take the toast and jammering......"+t);                t.jammer();                Thread.sleep(300);                finishedQueue.put(t);            }        } catch (InterruptedException e) {            System.out.println("Jammer InterruptedException");        }        System.out.println("Jammer Off!");    }}

5,Eater类

import java.util.Set;import java.util.concurrent.BlockingQueue;/** * 从finishedQueue获取任务并消费任务 * @author lecky * */public class Eater implements Runnable {    private BlockingQueue<Toast> finishedQueue;    private int counter=0;    public Eater(BlockingQueue<Toast> finishedQueue) {        this.finishedQueue = finishedQueue;    }    @Override    public void run() {        try {            while (!Thread.interrupted()){                Toast t = finishedQueue.take();                if(++counter != t.getId() || Toast.Status.JAMMED !=t.getStatus()){                    System.out.println("error>>>>"+t);                    System.exit(0);                }                System.out.println("eater take the toast and eat...."+t);            }        } catch (InterruptedException e) {            System.out.println("eater InterruptedException");        }        System.out.println("eater off!");    }}

6,测试类

import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingDeque;import org.junit.After;import org.junit.Before;import org.junit.Test;public class ToastMatic {    @Test    public void test() throws InterruptedException {        ExecutorService executor = Executors.newCachedThreadPool();        BlockingQueue<Toast> dryQueue = new LinkedBlockingDeque<Toast>();        BlockingQueue<Toast> butteredQueue = new LinkedBlockingDeque<Toast>();        BlockingQueue<Toast> finishedQueue = new LinkedBlockingDeque<Toast>();        executor.execute(new Eater(finishedQueue));        executor.execute(new Jammer(butteredQueue, finishedQueue));        executor.execute(new Butterer(dryQueue, butteredQueue));        executor.execute(new Toaster(dryQueue));        Thread.sleep(5*1000);        System.out.println("shunDown");        executor.shutdownNow();;    }}

[1].Thinking in java

0 0