java设计模式进阶_poison-pill

来源:互联网 发布:美食的意义知乎 编辑:程序博客网 时间:2024/06/10 04:02

这里写图片描述

//////  Generated by StarUML(tm) Java Add-In////  @ Project : Untitled//  @ File Name : MQPublishPoint.java//  @ Date : 2016/9/5//  @ Author : ////public interface MQPublishPoint {    public void put(Message message) throws InterruptedException;}//////  Generated by StarUML(tm) Java Add-In////  @ Project : Untitled//  @ File Name : MQSubscribePoint.java//  @ Date : 2016/9/5//  @ Author : ////public interface MQSubscribePoint {    public Message take() throws InterruptedException;}//////  Generated by StarUML(tm) Java Add-In////  @ Project : Untitled//  @ File Name : MessageQueue.java//  @ Date : 2016/9/5//  @ Author : ////public interface MessageQueue extends MQPublishPoint, MQSubscribePoint {}import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;//////  Generated by StarUML(tm) Java Add-In////  @ Project : Untitled//  @ File Name : SimpleMessageQueue.java//  @ Date : 2016/9/5//  @ Author : ////public class SimpleMessageQueue implements MessageQueue {    public BlockingQueue<Message> queue;    public SimpleMessageQueue(int size) {        queue = new ArrayBlockingQueue<Message>(size);    }    public void put(Message message) throws InterruptedException {        queue.put(message);    }    public Message take() throws InterruptedException {        return queue.take();    }}import com.think.in.java.design.pattern.lesson35.Message.Headers;//////  Generated by StarUML(tm) Java Add-In////  @ Project : Untitled//  @ File Name : Consumer.java//  @ Date : 2016/9/5//  @ Author : ////public class Consumer implements MQSubscribePoint {    private final MQSubscribePoint queue;    private String name;    public Consumer(String name, MQSubscribePoint queue) {        this.name = name;        this.queue = queue;    }    public void consume() {        while(true)        {            Message msg;            try {                msg = take();                if(msg == Message.POISON_PILL)                {                    System.out.println(String.format("Consumer %s receive request to terminate.", name));                    break;                }            } catch (Exception e) {                System.err.println(e);                return ;            }            String sender = msg.getHeader(Headers.SENDER);            String body = msg.getBody();            System.out.println(String.format("Message [%s] from [%s] received by [%s]", body, sender, name));        }    }    @Override    public Message take() throws InterruptedException {        return queue.take();    }}import java.util.Date;import com.think.in.java.design.pattern.lesson35.Message.Headers;//////  Generated by StarUML(tm) Java Add-In////  @ Project : Untitled//  @ File Name : Producer.java//  @ Date : 2016/9/5//  @ Author : ////public class Producer implements MQPublishPoint {    private final MQPublishPoint queue;    private final String name;    private boolean isStopped;    public Producer(String name, MQPublishPoint queue) {        this.name = name;        this.queue = queue;        this.isStopped = false;    }    public void send(String body) {        if(isStopped)        {            throw new IllegalStateException(String.format("Producer %s was stopped and fail to deliver requested message [%s].",body,name));        }        Message msg = new SimpleMessage();        msg.addHeader(Headers.DATE,new Date().toString());        msg.setBody(body);        put(msg);    }    public void stop() {        isStopped = true;        put(Message.POISON_PILL);    }    public void put(Message message) {        try {            queue.put(message);        } catch (Exception e) {            System.err.println(e);        }    }}import java.util.Map;public interface Message {    public static final Message POISON_PILL = new Message(){        @Override        public void addHeader(Headers header, String value) {            throw poison();        }        @Override        public String getHeader(Headers header) {            throw poison();        }        @Override        public Map<Headers, String> getHeaders() {            throw poison();        }        @Override        public void setBody(String body) {            throw poison();        }        @Override        public String getBody() {            throw poison();        }        private RuntimeException poison(){            return new UnsupportedOperationException("Poison");        }    };    public enum Headers{        DATE,   //日期        SENDER  //发送者    }    void addHeader(Headers header,String value);    String getHeader(Headers header);    Map<Headers,String> getHeaders();    void setBody(String body);    String getBody();}import java.util.Collections;import java.util.HashMap;import java.util.Map;public class SimpleMessage implements Message{    private Map<Headers,String> headers = new HashMap<>();    private String body;    @Override    public void addHeader(Headers header, String value) {        headers.put(header, value);    }    @Override    public String getHeader(Headers header) {        return headers.get(header);    }    @Override    public Map<Headers, String> getHeaders() {        return Collections.unmodifiableMap(headers);    }    @Override    public void setBody(String body) {        this.body = body;    }    @Override    public String getBody() {        return body;    }}/** * One of possible approaches to terminate Producer-Consumer pattern is using PoisonPill idiom. * If you use PoisonPill as termination signal then Producer is responsible to notify Consumer that exchange is over * and reject andy further messages.Consumer receiving PoisonPill will stop to read messages from queue. * You also must ensure that PoisonPill will be last message that will be read from queue (if you have * prioritized queue than this can be tricky). * In simple cases as PoisonPill can be used just null-reference,but holding unique separate share * object-marker (with name"Poison" or "PoisonPill") is more clear and self describing. */public class App {    public static void main(String[] args) {        MessageQueue queue = new SimpleMessageQueue(10000);        final Producer producer = new Producer("PRODUCER_1",queue);        final Consumer consumer = new Consumer("CONSUMER_1",queue);        new Thread(){            public void run(){                consumer.consume();            }        }.start();        new Thread(){            public void run()            {                producer.send("hand shake");                producer.send("some very important information");                producer.send("bye!");                producer.stop();            }        }.start();    }}/*Message [hand shake] from [null] received by [CONSUMER_1]Message [some very important information] from [null] received by [CONSUMER_1]Message [bye!] from [null] received by [CONSUMER_1]Consumer CONSUMER_1 receive request to terminate.*/
0 0
原创粉丝点击