六、生产者消费者模式(Producer-Consumer)
1、核心思想
通过管道对数据的生产者和消费者进行解耦,使二者不直接交互,从而使二者的处理速率相对来说互不影响。
2、注意通道积压
a、使用阻塞队列。
b、使用带流量控制的无界阻塞队列。
3、可复用代码
无
4、参考网站
Semaphore信号量控制
学习地址:http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html
Deque与LinkedBlockingDeque深入分析
学习地址:http://blog.csdn.net/vernonzheng/article/details/8267541
5、关联模式:Two-Phase模式
http://blog.csdn.net/huzhiqiangCSDN/article/details/55099853
public interface Chanel<P> {
public P take() throws InterruptedException;
public void put(P product) throws InterruptedException;
}
public class BlockingQueueChanel<P> implements Chanel<P> {
//便于使用不同的队列不用改外面的代码
private final BlockingQueue<P> queue;
public BlockingQueueChanel(BlockingQueue<P> queue) {
this.queue = queue;
}
@Override
public P take() throws InterruptedException {
return queue.take();
}
@Override
public void put(P product) throws InterruptedException {
queue.put(product);
}
}
/**
* 基于Semaphore的支持流量控制的通道实现
* @author huzhiqiang
* @param
*/
public class SemaphoreBaseChanel
implements Chanel
{
//便于使用不同的队列不用改外面的代码
private final BlockingQueue
queue;
private final Semaphore semaphore;
/**
* @param queue 阻塞队列,通常是一个无界阻塞队列
* @param flowLimit 流量限制数
*/
public SemaphoreBaseChanel(BlockingQueue<P> queue, int flowLimit) {
this.queue = queue;
semaphore = new Semaphore(flowLimit);
}
@Override
public P take() throws InterruptedException {
return queue.take();
}
@Override
public void put(P product) throws InterruptedException {
semaphore.acquire();
try {
queue.put(product);
} finally{
semaphore.release();
}
}
}
public class AttachmentProssor {
private final Chanel chanel = new BlockingQueueChanel(new ArrayBlockingQueue(200));
//使用了优雅终止模式,消费者实例
private final AbstractTerminatableThread indexingThread = new AbstractTerminatableThread() {
@Override
protected void doRun() throws Exception {
System.out.println("consumer begin");
File file = null;
file = chanel.take();
try {
indexFile(file);
} catch (Exception e) {
e.printStackTrace();
}finally{
terminationToken.reservations.decrementAndGet();
}
}
private void indexFile(File file) {
Random r = new Random();
try {
Thread.sleep(r.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
public void init(){
indexingThread.start();
}
public void shutdown() {
indexingThread.terminate();
}
//生产方法
public void saveAttachment(){
File file = new File("");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
chanel.put(file);
System.out.println("producer OK");
} catch (InterruptedException e) {
}
indexingThread.terminationToken.reservations.incrementAndGet();
}
}
public class Main {
public static void main(String[] args) {
AttachmentProssor attachmentProssor = new AttachmentProssor();
attachmentProssor.init();
new Thread(){
public void run() {
for(int i=0; i<1000; i++){
attachmentProssor.saveAttachment();
}
};
}.start();
new Thread(){
public void run() {
for(int i=0; i<1000; i++){
attachmentProssor.saveAttachment();
}
};
}.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
attachmentProssor.shutdown();
}
}