响应式编程Reactor——学习2

自定义线程调度
响应式:响应式编程、全异步、消息、事件回调
默认还是当前线程,生成整个流、发布流、订阅流、流操作

Flux.range(1,10)
		.publishOn(Schedulers.single()) //在哪个线程池就把这个流的数据和操作执行了
		.log()
		.subscribe();
// publishOn:改变发布者所在线程池
// subscribeOn:改变订阅者所在的线程池
public void thread1(){
	Scheduler s = Schedulers.newParallel("parallel-scheduler",4);
	final Flux<String> flux = Flux
		.range(1,2)
		.map(i -> i + 10)
		.log()
		.publishOn(s)
		.map(i -> "value" + i);
	// 只要不指定线程池,默认发布者用的线程就是订阅者的线程;
	new Thread(()->flux.subscribe(System.out::println)).start();
}
// flatMap扁平化
void flatMap(){
	Flux.just("zhang san","li si")
		.flatMap(v->{
			String[] s = v.split(" ");
			return Flux.fromArray(s);//把数据包装成多元素流
		})
		.log() //打日志
		.subscribe();// 两个人的名字,按照空格拆分,打印出所有的姓与名
}

concatMap:一个元素可以 变很多单个
流拼接操作,对于元素类型无限制
concatWith:老流拼接新的流,连接的流和老流中元素的类型相同
merge是合并,concat是拼接追加,zip流进行结对操作(编程元组的类型,最多支持8流压缩)

错误处理
默认:subscribe消费者可以感知 正常元素try与流发生的错误catch
错误是一种中断行为

//1、Catch and return a static default value捕获异常返回一个静态默认值
try {
	return doSomethingDangerous(10);
}
catch (Throwable error) {
	return "RECOUVERED";
}
//onErrorReturn()实现上面效果,错误的时候返回一个值
// 1、吃掉异常,消费者无异常感知
// 2、返回一个默认值
// 3、流正常完成
//2、Catch and execute an alternative path with a fallback method.
// 吃掉异常,执行一个兜底方法:
try {
	return doSomethingDangerous(10);
}
catch (Throwable error) {
	return doOtherthing(10);
}
// onErrorResume()
//1、吃掉一场,消费者无异常感知
//2、调用一个兜底方法
//3、流正常完成
//3、Catch and dynamically compute a fallback value.捕获并动态计算一个返回值
// 根据错误返回一个新值
try {
	Value v = erroringMethod();
	return MyWrapper.fromValue(v);
}
catch (Throwable error) {
	return MyWrapper.fromError(error);
}
// 4、Catch, wrap to a BusinessException,and re-throw捕获并包装成一个业务异常,并重新抛出
try {
	return callExternalService(k);
}
catch (throwable error) {
	throw new BusinessException("opps, SLA exceeded", error)
}
// 包装重新抛出异常,推荐用onErrorMap(err->new BusinessException(err.getMessage()))
// 1、吃掉异常,消费者有感知
// 2、抛新异常
// 3、流异常完成
// 5、Catch,log an error-specific message, and re-throw捕获异常,记录特殊的错误,重新抛出
具体案例看使用手册
// 异常被捕获,做自己的事情
// 不影响异常继续顺着流水线传播
// 1、不吃掉异常,只在异常发生的时候做一件事,消费者有感知

超时与重试
timeout与retry
在这里插入图片描述

工具sinks

/*
Sinks.many(); 发送Flux数据
Sinks.one(); 发送Mono数据
Sinks:接收器,数据管道,所有数据顺着这个管道往下走
*/
Sinks.many().unicast();//单播,这个管道只能绑定单个订阅者(消费者)
Sinks.many().multicast();//多播,这个管道能绑定多个订阅者
Sinks.many().replay();//重放,这个管道能重返元素,是否给后来的订阅者把之前的元素依然发给它

//从头消费还是从订阅的那一刻消费

Sinks.Many<Object> many = Sinks.many()
		.multicast() //多播
		.onBackpressureBuffer(); //背压队列
// 默认订阅者,从订阅的那一刻开始接元素

// 发布这数据重放,底层利用队列进行缓存之前数据
// Sinks.Many<Object> many = Sinks.many().replay().limit(3);

new Thread(()->{
	for (int i = 0; i < 10; i++) {
		many.tryEmitNext("a" + i);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
	}
}).start

//订阅
many.asFlux().subscribe(v-> System.out.println("v1= " + v));

new Thread(()->{
	try {
		Thread.sleep(5000);
	} catch (InterruptedException e) {
		throw new RuntimeException(e);
	}
	many.asFlux().subscribe(v-> System.out.println("v2 = " + v));
}).start();

缓存
.cache()
使用案例使用手册有,较为简单

List<Integer> integers = Flux.just(1,2,4)
		.map(i -> i + 10)
		.collectList()
		.block(); // 也是一种订阅者,阻塞式API
sout(integers)
void parallelFlux() {
	// 百万数据,8个线程,每个线程处理100,进行分批处理一直处理结束
	Flux.range(1,100)
		.buffer(10)
		.parallel(8) // 8个并发线程
		.runOn(Schedulers.newParaller("yy"))
		.log()
		.subscribe(v-> System.out.println("v = " + v)));
}
// 支持Context的中间操作
Flux.just(1,2,3)
	.transformDeferredContextual((flux, context)->{
		System.out.println("flux = " + flux);
		System.out.println("context = " + context);
		return flux.map(i->i+"==>"+context.get("prefix"));
	})
	// 上游能拿到下游的最近一次数据
	.contextWrite(Context.of("prefix","哈哈"))
	// ThreadLocal共享了数据,上有的所有人能看到,Context由下游传播给上游
	.subscribe(v -> sout())
// 以前命令式编程
// controller -- service -- dao
// 响应式编程 dao(10:数据源)-- service(10) -- controller(10);从下游反向传播
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

协奏曲❤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值