• java并发的发布和订阅测试


    现在编码的时候,为了处理消息,大家动不动就上个重器,例如MQ之类的。但很多时候,并不是那么有必要,因为数据量和并发其实远远不够。

    可以替代的方案非常多,其中一个是java.util.concurrent

    在jdk9及其以上,java.util.Observable已经被标注为过时,官方推荐使用java.beans或者是java.util.concurrent。

    在发布订阅者模式中,有四个对象是需要关注的:

    1. 发布者
    2. 订阅者(消费者)
    3. 消息
    4. 并发

    本文主要代码参考 https://www.cnblogs.com/zhangmingda/p/14715139.html

    不过为了更加友好一些,对原有的代码做了适量的调整。

    注:以下代码运行于windows11+JDK17

    消息对象

    package study.base.designPattern.observer.latest.flow;
    
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class Message {
        private Integer qty;
        private Integer maxQty;
        private String content;
        private Map<String, Boolean> readStatus;
    
        public Map<String, Boolean> getReadStatus() {
            return readStatus;
        }
    
        public String getContent() {
            return content;
        }
    
        public boolean isFinished() {
            return qty.intValue() == maxQty.intValue();
        }
    
        public Message(String content, List<String> readerList) {
            this.content = content;
            this.maxQty = readerList.size();
            this.qty = 0;
            this.readStatus = new ConcurrentHashMap<>();
            for (String item : readerList) {
                readStatus.put(item, false);
            }
        }
    
        public void read(String readerName) {
            if (qty < maxQty) {
                if (readStatus.containsKey(readerName)) {
                    Boolean isRead = readStatus.get(readerName);
                    if (!isRead) {
                        synchronized (readStatus) {
                            readStatus.put(readerName, true);
                            qty++;
                            System.out.println("---|"+readerName + "正在进行" + this.content + "...." + qty);
                            if (qty==maxQty) {
                                System.out.println("\n---|所有人已经完成【"+this.content+"】\n");
                            }
                        }
                    }
                }
            }
            
    
        }
    }

    消费者对象

    package study.base.designPattern.observer.latest.flow;
    
    import java.util.concurrent.Flow.Subscriber;
    import java.util.concurrent.Flow.Subscription;
    
    public class Student implements Subscriber<Message> {
    
        private Subscription subscription;
        private String name;
    
        public Student(String name) {
            this.name = name;
        }
    
        @Override
        public void onSubscribe(Subscription subscription) {
            System.out.println(name + "开始订阅[" + subscription.toString() + "]");
            subscription.request(1);
            this.subscription = subscription;
        }
    
        @Override
        public void onError(Throwable e) {
            System.out.println(e.getMessage());
        }
    
        @Override
        public void onComplete() {
            System.out.println(name + "关闭了订阅");
            Teacher.getLock().lock();
            Teacher.getCondition().signalAll();
            Teacher.getLock().unlock();
    
        }
    
        @Override
        public void onNext(Message message) {
            message.read(this.name);
            subscription.request(1);
            /**
             * 模拟延时--郊游的时候,时间长一些
             */
            try {
                if (message.getContent().equals("郊游")) {
                    Thread.sleep(1300);
                }
                else {
                    Thread.sleep(200);
                }
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    
    }

    发布者和主程序

    package study.base.designPattern.observer.latest.flow;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.SubmissionPublisher;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    
    /**
     * https://www.cnblogs.com/zhangmingda/p/14715139.html 此类技术是观察者模式的一个并发实现
     * 
     * @author lzfto
     */
    public class Teacher {
        private static Lock lock = new ReentrantLock(true);
        private static Condition condition = lock.newCondition();
    
        private volatile static CopyOnWriteArrayList<Message> subjectList = new CopyOnWriteArrayList<Message>();
    
        public static Lock getLock() {
            return lock;
        }
    
        public static Condition getCondition() {
            return condition;
        }
    
        public static void main(String[] args) throws InterruptedException {
    
            /**
             * 定义一个发布者,需要设定要发送消息的泛型数据类型
             */
            SubmissionPublisher<Message> teacher = new SubmissionPublisher<>();
            /**
             * 定义一个订阅者
             */
            List<String> studentList = Arrays.asList("mzd", "***", "luzhfiei", "海瑞");
            for (String readerName : studentList) {
                Student student = new Student(readerName);
                teacher.subscribe(student);
            }
            /**
             * 测试发布消息
             */
    
            subjectList.add(new Message("朗读", studentList));
            subjectList.add(new Message("劳动", studentList));
            subjectList.add(new Message("郊游", studentList));
            subjectList.add(new Message("射箭", studentList));
    
            subjectList.forEach(item -> {
                System.out.println("同学们!开始【" + item.getContent() + "】");
                teacher.submit(item);
            }); // 向订阅者发布数据,需要保持主线程存活,否则当前线程执行结束,发布者和订阅者都被销毁了。
            /**
             * 关闭消息发布
             */
            teacher.close(); // 关闭后,如果当前线程未退出,待订阅者所有消息都处理完毕才会运行订阅者的onComplete方法
            lock.lock();
            condition.await();
            lock.unlock();
            System.out.println(JSONArray.toJSONString(subjectList, SerializerFeature.PrettyFormat));
            ;
        }
    
    }

    测试后的输出(一种情况):

    mzd开始订阅[java.util.concurrent.SubmissionPublisher$BufferedSubscription@12749d9e]
    ***开始订阅[java.util.concurrent.SubmissionPublisher$BufferedSubscription@1df086d4]
    luzhfiei开始订阅[java.util.concurrent.SubmissionPublisher$BufferedSubscription@1e7629c2]
    海瑞开始订阅[java.util.concurrent.SubmissionPublisher$BufferedSubscription@73e441ec]
    同学们!开始【朗读】
    同学们!开始【劳动】
    同学们!开始【郊游】
    同学们!开始【射箭】
    ---|mzd正在进行朗读....1
    ---|海瑞正在进行朗读....2
    ---|luzhfiei正在进行朗读....3
    ---|***正在进行朗读....4
    
    ---|所有人已经完成【朗读】
    
    ---|海瑞正在进行劳动....1
    ---|luzhfiei正在进行劳动....2
    ---|***正在进行劳动....3
    ---|mzd正在进行劳动....4
    
    ---|所有人已经完成【劳动】
    
    ---|***正在进行郊游....1
    ---|mzd正在进行郊游....2
    ---|luzhfiei正在进行郊游....3
    ---|海瑞正在进行郊游....4
    
    ---|所有人已经完成【郊游】
    
    ---|mzd正在进行射箭....1
    ---|***正在进行射箭....2
    ---|luzhfiei正在进行射箭....3
    ---|海瑞正在进行射箭....4
    
    ---|所有人已经完成【射箭】
    
    luzhfiei关闭了订阅
    ***关闭了订阅
    mzd关闭了订阅
    海瑞关闭了订阅

    subjectList的结果:

    [
        {
            "content": "朗读",
            "finished": true,
            "readStatus": {
                "mzd": true,
                "海瑞": true,
                "***": true,
                "luzhfiei": true
            }
        },
        {
            "content": "劳动",
            "finished": true,
            "readStatus": {
                "mzd": true,
                "海瑞": true,
                "***": true,
                "luzhfiei": true
            }
        },
        {
            "content": "郊游",
            "finished": true,
            "readStatus": {
                "mzd": true,
                "海瑞": true,
                "***": true,
                "luzhfiei": true
            }
        },
        {
            "content": "射箭",
            "finished": true,
            "readStatus": {
                "mzd": true,
                "海瑞": true,
                "***": true,
                "luzhfiei": true
            }
        }
    ]

    这只是一个非常简单的例子,距离生产还有很远的一个距离。

  • 相关阅读:
    marshaller unmarshaller解析xml和读取xml
    request请求地址
    SAP系统接口方式:
    SAP 后台job
    查找系统锁对象
    动态生成ABAP程序-资料
    BDC程序步骤
    ABAP 创建测试文件
    ALE和IDocs
    ABAP锁,数据库锁
  • 原文地址:https://www.cnblogs.com/lzfhope/p/16289546.html
Copyright © 2020-2023  润新知