Reactive

本文通过简易的代码示例展示了Reactive编程中的发布者和订阅者关系。Reactive编程允许根据处理速度动态调节数据发布的频率,通过内部缓冲池实现消息缓存。当订阅者的缓冲池满时,发布者的submit方法会被阻塞,达到控制数据生成速率的效果。通过修改代码,观察运行结果,揭示了Reactive编程中订阅者如何影响发布者的发布速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念不多做介绍,直接看代码,简易demo

public class FlowDemo {
    public static void main(String[] args) {
        //定义发布者
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
        //定义订阅者
        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            private Subscription subscription;
            @Override
            public void onSubscribe(Flow.Subscription subscription) {
                //保存订阅关系,用它来给发布者响应
                this.subscription = subscription;
                //告诉发布者需要一个数据
                this.subscription.request(1);
            }

            @Override
            public void onNext(Integer item) {
                //接收到一个数据并做处理
                System.out.println("接收到数据:" + item);
                //处理完后再请求一个数据
                this.subscription.request(1);
                //或者已经达到目标,告诉发布者不再接收数据
//                this.subscription.cancel();
            }

            @Override
            public void onError(Throwable throwable) {
                //出现异常
                throwable.printStackTrace();
                //告诉发布者不再接收数据
                this.subscription.cancel();
            }

            @Override
            public void onComplete() {
                //全部处理完(发布者关闭)
                System.out.println("处理完成");
            }


        };
        //建立发布者和订阅者的订阅关系
        publisher.subscribe(subscriber);
        //产生数据并发布
        publisher.submit(111);
        publisher.submit(222);
        publisher.submit(333);
        //结束后关闭发布者
        //正式环境放finally里或用try-resource确保关闭
        publisher.close();
        //延迟,否则主线程会很快
        try {
            Thread.currentThread().join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:

实现了发布者和订阅者的关系,需要多注意的是,这里可做调节,如果处理的慢,处理下一个的频率就慢,反之就快,这里起到了调节发布者发送频率的作用。

再看一个:

这里的输入数据,过滤掉小于0的,并转成字符串发布出去。

class MyProcessor extends SubmissionPublisher<String> 
        implements Processor<Integer , String>{

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

    @Override
    public void onNext(Integer item) {
        System.out.println("处理器接收到数据:" + item);
        if (item > 0){
            this.submit(String.valueOf(item));
        }
        this.subscription.request(1);
//        this.subscription.cancel();
    }

    @Override
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
        this.subscription.cancel();
    }

    @Override
    public void onComplete() {
        System.out.println("处理器处理完成");
        this.close();
    }
}
public class FlowDemo2 {
    public static void main(String[] args) {
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
        MyProcessor myProcessor = new MyProcessor();
        publisher.subscribe(myProcessor);
        Subscriber<String> subscriber = new Subscriber<>() {
            private Subscription subscription;
            @Override
            public void onSubscribe(Subscription subscription) {
                //保存订阅关系,用它来给发布者响应
                this.subscription = subscription;
                //告诉发布者需要一个数据
                this.subscription.request(1);
            }

            @Override
            public void onNext(String item) {
                //接收到一个数据并做处理
                System.out.println("订阅者接收到数据:" + item);
                //处理完后再请求一个数据
                this.subscription.request(1);
                //或者已经达到目标,告诉发布者不再接收数据
//                this.subscription.cancel();
            }

            @Override
            public void onError(Throwable throwable) {
                //出现异常
                throwable.printStackTrace();
                //告诉发布者不再接收数据
                this.subscription.cancel();
            }

            @Override
            public void onComplete() {
                //全部处理完(发布者关闭)
                System.out.println("处理完成");
            }
        };
        myProcessor.subscribe(subscriber);
        publisher.submit(-10);
        publisher.submit(12);
        publisher.close();
        try {
            Thread.currentThread().join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:

这里发布者不直接跟订阅者建立关系,而是通过处理器。

那么发布者和订阅者是如何协调的呢?

通过断点可以看到,subscription里有个数组,,长度是32,最大可变为256,这里可视为缓冲池,把发布者发过来的消息缓存起来,消费的时候直接从这里取。

那么订阅者如何使发布者发布速度慢下来呢?发布者的submit方法是阻塞方法,当订阅者的缓冲池满了,submit就会被阻塞,就停下来了。

改下代码

public class FlowDemo {
    public static void main(String[] args) {
        //定义发布者
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
        //定义订阅者
        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            private Subscription subscription;
            @Override
            public void onSubscribe(Flow.Subscription subscription) {
                //保存订阅关系,用它来给发布者响应
                this.subscription = subscription;
                //告诉发布者需要一个数据
                this.subscription.request(1);
            }

            @Override
            public void onNext(Integer item) {
                //接收到一个数据并做处理
                System.out.println("接收到数据:" + item);
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //处理完后再请求一个数据
                this.subscription.request(1);
                //或者已经达到目标,告诉发布者不再接收数据
//                this.subscription.cancel();
            }

            @Override
            public void onError(Throwable throwable) {
                //出现异常
                throwable.printStackTrace();
                //告诉发布者不再接收数据
                this.subscription.cancel();
            }

            @Override
            public void onComplete() {
                //全部处理完(发布者关闭)
                System.out.println("处理完成");
            }
        };
        //建立发布者和订阅者的订阅关系
        publisher.subscribe(subscriber);
        //产生数据并发布
        for (int i = 0 ; i < 1000 ; i ++){
            System.out.println("生产数据:" +  i);
            publisher.submit(i);
        }
        //结束后关闭发布者
        //正式环境放finally里或用try-resource确保关闭
        publisher.close();
        //延迟,否则主线程会很快
        try {
            Thread.currentThread().join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

一开始,会生成236条数据,因为缓冲池最大256,所以当到256后就不会再生成了

接下来每消费一条数据,就会再接着生产一条

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值