RxJava的核心原理是不是这样的?

        最近看到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

发布了38 篇原创文章 · 获赞 6 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章