java语言中提供了blockingQueue阻塞队列以及几种实现:
在解决多线程生产者,消费者问题的时候,可以使用阻塞队列来代替java同步原语wati()和notify()以及sychronized。简化编程模型。
下面使用linkedBlockingQueue来简化生产者消费者问题[1]。
问题:有一台机器有三个任务,一个制作toast,一个抹黄油,一个涂果酱,还有一个消费toast的人,总共有四个任务,使用队列解决这四个任务之间的协同?
解决方法描述如下图:
阻塞队列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 dryQueue;
private int count=0;
public Toaster(BlockingQueue 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 dryQueue;
private BlockingQueue butterQueue;
public Butterer(BlockingQueue dryQueue,
BlockingQueue 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 butterQueue;
private BlockingQueue finishedQueue;
public Jammer(BlockingQueue butterQueue,
BlockingQueue 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 finishedQueue;
private int counter=0;
public Eater(BlockingQueue 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 dryQueue = new LinkedBlockingDeque();
BlockingQueue butteredQueue = new LinkedBlockingDeque();
BlockingQueue finishedQueue = new LinkedBlockingDeque();
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