前言

本文摘自于下面两篇文章:
中文参考最详细的模型解释
API翻译最有价值的例子
并且通过intellij写了例子并实验成功,下面记录一下实验过程。

代码结构

一个PublisherImpl和SubscriberImpl,main函数PublisherImpl里面。
主要流程:

  1. 生成一个分发杂志的publisher,2个邮递员subscriber一个叫jack,一个叫pete来消费(分发)杂志
  2. 可以调整publisher缓存的容量capacity,以及publisher对于timeout的设置(可以容忍多少时间subscriber才给回复)
  3. 可以调整subscriber的自由休息timeout时间,来测试publisher的反应(也就是其他文章里面所说的backpressure反压)
  4. 如果超出publisher的timeout,就把该元素放到缓存里面

设置场景:

  1. publisher小缓存容量,subscriber都是小timeout(快速反应) ----> 小缓存没有影响因为很快都发完了
  2. publisher大缓存容量,subscriber都是长timeout(反应缓慢) ----> 虽然缓慢处理,但是没有文件丢失,因为缓存很大
  3. publisher小缓存,subscriber一个中等timeout,一个超长timeout ----> 中等时间的没有文件丢失,超长时间的丢失了文件

代码

PublisherImpl.java

package mymoa.SubscriberTest;

import java.util.List;
import java.util.concurrent.Flow;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.SubmissionPublisher;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.stream.IntStream;

public class PublisherImpl implements PublisherInterface<Integer> {

    private static final int NUMBER_OF_MAGAZINES = 20;
    private static final long MAX_SECONDS_TO_KEEP_IT_WHEN_NO_SPACE = 2;
    private static final Logger log = Logger.getLogger(PublisherImpl.class.getName());


    @Override
    public void subscribe(Flow.Subscriber<? super Integer> subscriber) {

    }

    @Override
    public List<Flow.Subscriber<? super Integer>> getSubscribers() {
        return null;
    }


    public static void main(String [] args) throws Exception{
        final PublisherImpl publisher1 = new PublisherImpl();

        log.info("\n\n### CASE 1: Subscribers are fast, buffer size is not so " +
                "important in this case.");
        publisher1.magazineDeliveryExample(100L, 100L, 8);

        log.info("\n\n### CASE 2: A slow subscriber, but a good enough buffer " +
                "size on the publisher's side to keep all items until they're picked up");
        publisher1.magazineDeliveryExample(1000L, 3000L, NUMBER_OF_MAGAZINES);

        log.info("\n\n### CASE 3: A slow subscriber, and a very limited buffer " +
                "size on the publisher's side so it's important to keep the slow " +
                "subscriber under control");
        publisher1.magazineDeliveryExample(1000L, 3000L, 8);


    }

    void magazineDeliveryExample(final long sleepTimeJack,
                                 final long sleepTimePete,
                                 final int maxStorageInPO) throws Exception{
        final SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>(ForkJoinPool.commonPool(),maxStorageInPO);

        final SubscriberImpl jack = new SubscriberImpl(sleepTimeJack,SubscriberImpl.JACK);
        final SubscriberImpl pete = new SubscriberImpl(sleepTimePete,SubscriberImpl.PETE);

        publisher.subscribe(jack);
        publisher.subscribe(pete);

        log.info("printing 20 magazines per subscriber, with room in publisher for"+maxStorageInPO
        +". They have "+MAX_SECONDS_TO_KEEP_IT_WHEN_NO_SPACE+ "seconds to consume each magazine");

        IntStream.rangeClosed(1,20).forEach((number)->{
            log.info("Offering magazine "+number+"to consumers");

            final int lag = publisher.offer(
                    number,
                    MAX_SECONDS_TO_KEEP_IT_WHEN_NO_SPACE,
                    TimeUnit.SECONDS,
                    (subscriber,msg)->{
                        subscriber.onError(
                                new RuntimeException("Hey "+((SubscriberImpl) subscriber).getSubscriberName() + "! You are too slow getting magazines"+
                                        "and we dont have more space for them! I'll drop your magazine: "+msg)
                        );
                        return false;
                    });
            if (lag<0){
                log.info("dropping "+-lag+"magazines");
            }else{
                log.info("the slowest consumer has "+lag+" magazines in total to be picked up");
            }
        });

        // blocks until all subscribers are done
        while (publisher.estimateMaximumLag() > 0){
            Thread.sleep(500L);
        }

        // closes the publisher
        publisher.close();

        // give some time to the slowest consumer to wake up and notice it's completed
        Thread.sleep(Math.max(sleepTimeJack,sleepTimePete));
    }
}

SubscriberImpl.java

package mymoa.SubscriberTest;

import java.util.concurrent.Flow;
import java.util.logging.Logger;
import java.util.stream.IntStream;

public class SubscriberImpl implements SubscriberInterface<Integer>{
    public static final String JACK = "jack";
    public static final String PETE = "pete";

    private final long sleepTime;
    private final String subscriberName;
    private Flow.Subscription subscription;
    private final static Logger logger = Logger.getLogger(SubscriberImpl.class.getName());
    private int nextMagazineExpected;
    private int totalRead;

    SubscriberImpl(final long sleepTime,final String subscriberName){
        this.sleepTime = sleepTime;
        this.subscriberName = subscriberName;
        this.nextMagazineExpected = 1;
        this.totalRead = 0;
    }

    private void log(final String logMessage){
        logger.info("<=========== [" + subscriberName + "] : " + logMessage);
    }

    @Override
    public String getSubscriberName() {
        return "this is a class "+subscriberName;
    }

    @Override
    public void onSubscribe(Flow.Subscription subscription) {
        this.subscription = subscription;
        // request publisher once
        subscription.request(1);
    }

    @Override
    public void onNext(final Integer magazineNumber) {
        if(magazineNumber != nextMagazineExpected){
            IntStream.range(nextMagazineExpected,magazineNumber).forEach(
                    (msgNumber)-> log("i mised the megazine "+msgNumber)
            );
            // catch up with the number
            nextMagazineExpected = magazineNumber;
        }
        log("Great! i gt a new magazine: "+magazineNumber);
        takeSomeRest();
        nextMagazineExpected++;
        totalRead++;

        log("the next one will be "+nextMagazineExpected);
        subscription.request(1);

    }

    private void takeSomeRest(){
        try{
            Thread.sleep(sleepTime);
        }catch(InterruptedException e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onError(final Throwable throwable) {
        log("opps error from the publisher: "+throwable.getMessage());
    }


    @Override
    public void onComplete() {
    log("finally! i completed the subscription, i got in total"+totalRead+" magazines.");
    }


}

关键点分析:

Publisher里面的offer函数

--->发布数据的函数,函数的定义如下

int offer(T item, long timeout, TimeUnit unit, BiPredicate<Flow.Subscriber<? super T>,? super T> onDrop)

代码里面对应的部分

final int lag = publisher.offer(
                    number,
                    MAX_SECONDS_TO_KEEP_IT_WHEN_NO_SPACE,
                    TimeUnit.SECONDS,
                    (subscriber,msg)->{
                        subscriber.onError(
                                new RuntimeException("Hey "+((SubscriberImpl) subscriber).getSubscriberName() + "! You are too slow getting magazines"+
                                        "and we dont have more space for them! I'll drop your magazine: "+msg)
                        );
                        return false;
                    });
            if (lag<0){
                log.info("dropping "+-lag+"magazines");
            }else{
                log.info("the slowest consumer has "+lag+" magazines in total to be picked up");
            }

解读:

  1. OnDrop是在要判断是否删除元素时候(超过timeout并且缓存不够)被调用:
    • 如果返回true,那么重新发送这个元素
    • 如果返回false,那么删除这个元素
  2. offer返回值:
    • 方法返回的负整数表示向订阅者发送元素失败的尝试次数;
    • 正整数表示在所有当前订阅者中提交但尚未消费的最大元素数量的估计。也可以通过 publisher.estimateMaximumLag()来获取

创建Publisher

函数定义

SubmissionPublisher(Executor executor, int maxBufferCapacity)

代码实现

final SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>(ForkJoinPool.commonPool(),maxStorageInPO);

解读:

  1. Executor向其订阅者提供元素(元素池)。 如果想要使用多个线程来生成要发布的元素并且可以估计订阅者数量,则可以使用具有固定线程池的newFixedThreadPool(int nThread)
  2. 默认的Executor,它使用ForkJoinPool类的commonPool()方法获取。

输出case3

### CASE 3: A slow subscriber, and a very limited buffer size on the publisher's side so it's important to keep the slow subscriber under control
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl magazineDeliveryExample
信息: printing 20 magazines per subscriber, with room in publisher for8. They have 2seconds to consume each magazine
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 1to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 1 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 1
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 1
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 2to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 2 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 3to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 3 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 4to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 4 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 5to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 5 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 6to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 6 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 7to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 7 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 8to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 8 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 9to consumers
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 9 magazines in total to be picked up
1月 06, 2021 4:40:23 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 10to consumers
1月 06, 2021 4:40:24 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 2
1月 06, 2021 4:40:24 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 2
1月 06, 2021 4:40:25 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 3
1月 06, 2021 4:40:25 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 3
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 2
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 2
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 4
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 4
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : opps error from the publisher: Hey this is a class pete! You are too slow getting magazinesand we dont have more space for them! I'll drop your magazine: 10
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: dropping 1magazines
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 11to consumers
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 9 magazines in total to be picked up
1月 06, 2021 4:40:26 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 12to consumers
1月 06, 2021 4:40:27 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 5
1月 06, 2021 4:40:27 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 5
1月 06, 2021 4:40:28 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 6
1月 06, 2021 4:40:28 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 6
1月 06, 2021 4:40:28 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : opps error from the publisher: Hey this is a class pete! You are too slow getting magazinesand we dont have more space for them! I'll drop your magazine: 12
1月 06, 2021 4:40:28 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: dropping 1magazines
1月 06, 2021 4:40:28 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 13to consumers
1月 06, 2021 4:40:29 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 3
1月 06, 2021 4:40:29 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 9 magazines in total to be picked up
1月 06, 2021 4:40:29 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 14to consumers
1月 06, 2021 4:40:29 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 3
1月 06, 2021 4:40:29 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 7
1月 06, 2021 4:40:29 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 7
1月 06, 2021 4:40:30 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 8
1月 06, 2021 4:40:30 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 8
1月 06, 2021 4:40:31 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : opps error from the publisher: Hey this is a class pete! You are too slow getting magazinesand we dont have more space for them! I'll drop your magazine: 14
1月 06, 2021 4:40:31 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: dropping 1magazines
1月 06, 2021 4:40:31 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 15to consumers
1月 06, 2021 4:40:31 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 9
1月 06, 2021 4:40:31 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 9
1月 06, 2021 4:40:32 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 4
1月 06, 2021 4:40:32 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 4
1月 06, 2021 4:40:32 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 9 magazines in total to be picked up
1月 06, 2021 4:40:32 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 16to consumers
1月 06, 2021 4:40:32 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 10
1月 06, 2021 4:40:32 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 10
1月 06, 2021 4:40:33 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 11
1月 06, 2021 4:40:33 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 11
1月 06, 2021 4:40:34 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : opps error from the publisher: Hey this is a class pete! You are too slow getting magazinesand we dont have more space for them! I'll drop your magazine: 16
1月 06, 2021 4:40:34 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: dropping 1magazines
1月 06, 2021 4:40:34 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 17to consumers
1月 06, 2021 4:40:34 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 12
1月 06, 2021 4:40:34 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 12
1月 06, 2021 4:40:35 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 5
1月 06, 2021 4:40:35 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 9 magazines in total to be picked up
1月 06, 2021 4:40:35 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 5
1月 06, 2021 4:40:35 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 18to consumers
1月 06, 2021 4:40:35 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 13
1月 06, 2021 4:40:35 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 13
1月 06, 2021 4:40:36 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 14
1月 06, 2021 4:40:36 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 14
1月 06, 2021 4:40:37 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : opps error from the publisher: Hey this is a class pete! You are too slow getting magazinesand we dont have more space for them! I'll drop your magazine: 18
1月 06, 2021 4:40:37 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: dropping 1magazines
1月 06, 2021 4:40:37 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 19to consumers
1月 06, 2021 4:40:37 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 15
1月 06, 2021 4:40:37 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 15
1月 06, 2021 4:40:38 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 6
1月 06, 2021 4:40:38 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: the slowest consumer has 9 magazines in total to be picked up
1月 06, 2021 4:40:38 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: Offering magazine 20to consumers
1月 06, 2021 4:40:38 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 6
1月 06, 2021 4:40:38 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 16
1月 06, 2021 4:40:38 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 16
1月 06, 2021 4:40:39 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 17
1月 06, 2021 4:40:39 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 17
1月 06, 2021 4:40:40 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : opps error from the publisher: Hey this is a class pete! You are too slow getting magazinesand we dont have more space for them! I'll drop your magazine: 20
1月 06, 2021 4:40:40 下午 mymoa.SubscriberTest.PublisherImpl lambda$magazineDeliveryExample$1
信息: dropping 1magazines
1月 06, 2021 4:40:40 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 18
1月 06, 2021 4:40:40 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 18
1月 06, 2021 4:40:41 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 7
1月 06, 2021 4:40:41 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 7
1月 06, 2021 4:40:41 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 19
1月 06, 2021 4:40:41 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 19
1月 06, 2021 4:40:42 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 20
1月 06, 2021 4:40:42 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : Great! i gt a new magazine: 20
1月 06, 2021 4:40:43 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : the next one will be 21
1月 06, 2021 4:40:44 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 8
1月 06, 2021 4:40:44 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 8
1月 06, 2021 4:40:47 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 9
1月 06, 2021 4:40:47 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 9
1月 06, 2021 4:40:50 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 10
1月 06, 2021 4:40:50 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : i mised the megazine 10
1月 06, 2021 4:40:50 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 11
1月 06, 2021 4:40:53 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 12
1月 06, 2021 4:40:53 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : i mised the megazine 12
1月 06, 2021 4:40:53 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 13
1月 06, 2021 4:40:56 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 14
1月 06, 2021 4:40:56 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : i mised the megazine 14
1月 06, 2021 4:40:56 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 15
1月 06, 2021 4:40:59 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 16
1月 06, 2021 4:40:59 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : i mised the megazine 16
1月 06, 2021 4:40:59 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 17
1月 06, 2021 4:41:02 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 18
1月 06, 2021 4:41:02 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : i mised the megazine 18
1月 06, 2021 4:41:02 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : Great! i gt a new magazine: 19
1月 06, 2021 4:41:05 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : the next one will be 20
1月 06, 2021 4:41:05 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [jack] : finally! i completed the subscription, i got in total20 magazines.
1月 06, 2021 4:41:05 下午 mymoa.SubscriberTest.SubscriberImpl log
信息: <=========== [pete] : finally! i completed the subscription, i got in total14 magazines.

Process finished with exit code 0