最近看到RxJava技术,好奇就网上找了些关于RxJava
的博文,但绝大部分文章都讲了其使用,可我对最基本的东西——概念还是一脸懵逼。
这些文章看后,大概我知道两个重点,一是类似于观察者模式,二是任务执行与通知可以设置不同的线程。具体这个框架源码怎么做的就不知道了。看源码太累了,很多有名的产品其实最核心的原理很简单,demo也很好实现。比如dubbo,就是客户端把调用方法与参数发过去,服务端根据invocation找到对应的service并执行,再把结果从远程发过来;又比如druid,就是把sql包中的一切都适配一下,中间插入我要的filterChain,比如统计的filter。所以我就想先按自己的理解,写几行代码,做一个小Demo实现两个重点,请大家看看是不是这样的原理。
核心业务:我作为观察者,注册到你这里,你就开始处理(我是参数)并把结果通知我,我接着处理。当然你处理和我处理都可以封成runnable扔到不同的线程池中。
与一般观察者模式不同的是,被观察者什么时候开始处理不知道(也许是被其它调用,也许是监听到什么,也许...),而这里是观察者注册的那一时刻。
操作符:我作为观察者,操作符会造成你被一个新产生的中间人代理了。这时我注册到中间人,中间人开始处理(我是参数)并产生一个中间观察者注册到你这里,你处理后,结果给中间观察者处理,中间观察者处理后,再给我(参数)处理。
话不多说,上代码(不包含操作符):
package com.rxjava.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
/**
* 学习rxjava的原理
*
* 【思考】: 如果作为框架,call函数功能也应该从外部提供,用内部类?用abstract方法?
* 如果call可给其它线程执行用哪个方案?用内部类?
*
* @author ACER
* @date 2019年11月24日
*/
public class RxjavaTest {
// 配置用其它线程执行时,订阅者的操作在这里执行
private static ExecutorService ioExecutor;
private static final AtomicLong threadIndex = new AtomicLong(0);// 线程计数
private static int cupNum = Runtime.getRuntime().availableProcessors();// cpu数
static {
System.out.println("cpu:" + cupNum);
ioExecutor = new ThreadPoolExecutor(cupNum, cupNum, 1000 * 60,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(100),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "io_thread_"
+ threadIndex.incrementAndGet());
return thread;
}
});
}
public static void main(String[] args) {
RxjavaTest test = new RxjavaTest();
test.regListen(new Listenner() {
@Override
public void OnNext(int plusValue) {
System.out.println("copy that!!!->" + plusValue);
}
});
System.out.println("---------------【修改为不同的线程执行】------------------");
test.useSameThread = false;
test.regListen(new Listenner() {
@Override
public void OnNext(int plusValue) {
System.out.println("copy that in anather thread!!!->"
+ plusValue);
}
});
}
public boolean useSameThread = true;// 是否用同一线程
public Listenner _listenner;// 注册进来的订阅者
// 注册操作。同时就调用执行相关服务,执行过程中会通知订阅者。
void regListen(Listenner li) {
_listenner = li;
// 有人注册了,开始工作
if (_listenner != null) {
call(_listenner);
}
}
// 真正的服务过程(其实也可以给其它线程去运行)
public void call(Listenner listenner) {
int a = 4;
int b = 6;
if (useSameThread) {
listenner.OnNext(a + b);
b = 45;
listenner.OnNext(a + b);
} else {
// 后面扔到线程池执行
final int result = a + b + 100;
ioExecutor.submit(new listenRun(listenner, result));
final int result2 = a + b + 1000;
ioExecutor.submit(new listenRun(listenner, result2));
}
}
//配置其它线程时:订阅者执行用其它线程,产生的Runnable对象。
public class listenRun implements Runnable {
public Listenner lisInner;
private int resultInner;
public listenRun(Listenner a, int b) {
lisInner = a;
resultInner = b;
}
@Override
public void run() {
System.out
.println("ThreadName:" + Thread.currentThread().getName());
lisInner.OnNext(resultInner);
}
}
// 订阅者应实现的接口
public static interface Listenner {
void OnNext(int plusValue);
}
}
这是执行结果:
cpu:4
copy that!!!->10
copy that!!!->49
---------------【修改为不同的线程执行】------------------
ThreadName:io_thread_1
ThreadName:io_thread_2
copy that in anather thread!!!->110
copy that in anather thread!!!->1010
当然上面的代码如果把call过程也配置一下,放入另外的线程池就更好了。最后再改造成一个框架,从外部传入call的操作就更完善了。
欢迎大家指点一下,谢谢!
注:刚看到这个文章,写的不错。https://blog.csdn.net/TellH/article/details/71534704