(4.6.22.2)来吧,是时候撸一份自己的RxJava框架啦:代理模式实现线程调度
来源:互联网 发布:微信小视频修改软件 编辑:程序博客网 时间:2024/05/17 15:17
看了上篇(4.6.22.1)来吧,是时候撸一份自己的RxJava框架啦:观察者模式实现链式调用有木有觉得,线式调用很简单呢?
那么,重头戏来了,我们如何实现线程调度?
就是要借助代理模式,代理模式不懂的话,请转向(2.2.1)设计模式一览系列文章
线程调度的原理: 代理模式。
2.1 所有类的成员函数的调用都不是直接由对应对象实例调用,而是由代理类去调用
2.2 通用的总代理类,实现线程调度
- 设计思路图
- 设计思路
- 实践
- 两个注解 标示线程调度 和 延迟
- 发布者被观察者 事件的产生者 的代理
- 观察者消费者 事件的消费者 的代理
- 线程调度分发器
- 1 线程调度方法
- 2 一种线程调度NewThread 创建新线程
- 3 动态调用 对象函数参数
- 31 函数代理模式函数分发模型
- 函数代理
- 发布者被观察者 事件的产生者的函数代理
- 观察者消费者 事件的消费者的函数代理
- 31 函数代理模式函数分发模型
- Test
- 线程调度的自行实现
设计思路图
在(4.6.22.1)的模式中,我们是直接调用 生产者.call()函数,和 消费者.onSuccess()函数,直接调用那么自然意味着不会有线程调度的时机了
|
不能直接调用 生产者|消费者的对应成员方法,不调用?
|
使用代理模式,做分别的代理类,代理类根据对应的函数注解,在不同的线程执行被代理类对象的成员函数
|
优化空间? 线程的调度模型应该是一样,应该做一个统一的调度模型,实现消费者or生产者的调度是通过同一种调度模型实现
|
那就是搞一个 线程调度分发器喽
一句话:使每个对象的成员方法通过我们的调度器Invoker调用,而不是直接被调用
设计思路
核心的业务控制器
- Future invoke(Method method, Object object, Object… values)
实现线程调度:获取method的对应注解,根据注解在不同线程–调用object的method方法,并传入values参数
有返回数据,由于是线程调度,不能直接返回数据,而是返回Future实例 ((2.2.2.9)Future接口和FutureTask类【FutureTask实现了Runnable和Future接口】)
- Future invoke(Method method, Object object, Object… values)
【发布者—被观察者 : 事件的产生者】 的代理
- 实现 生产者的接口—代理模式的基本需求
- 持有 实际的生产者实例
- 重写 生产者接口的对应函数: 注意不能直接调用被代理对象的成员函数,而是交由 线程调度器统一处理
- 开放 返回的Future实例
【观察者—消费者: 事件的消费者】 的代理
- 实现 消费者的接口—代理模式的基本需求
- 持有 实际的 消费者们 实例
- 重写 消费者接口的对应函数
注意1:不能直接调用被代理对象的成员函数,而是交由 线程调度器统一处理
注意2:遍历消费者们,代理类是所有消费者的代理,保证生产者.call(消费者)中调用消费者时,所有函数都会被执行 - 消费者容器的增删查
两个函数注解: 标示线程调度 和 延迟
实践
1. 两个注解: 标示线程调度 和 延迟
/** * 延迟执行 * Created by yhf on 16/12/18. */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Delay { int value()default 0;}
** * 默认为当前线程 * Created by yhf on 16/12/18. */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RunContext { RunContextType value()default RunContextType.CurrentThread;}/** * 线程调度类型 * Created by yhf on 16/12/18. */public enum RunContextType { MainThread, MainLoop, NewThread, NewHandlerThread, CurrentThread, CurrentLoop, IO, Calculate, Dynamic, Custome;}
2. 【发布者—被观察者 : 事件的产生者】 的代理
先看看代理模式的基本实现
/** * 【发布者---被观察者 : 事件的产生者】 的代理 * 使每个目标方法通过我们的调度器Invoker调用,而不是直接被调用,OnObserver和OnPublisher必须被代理 * 从而,实现 线程调度 * 否则用户就可以直接调用,没法实现线程调度 * - 实现 生产者的接口---代理模式的基本需求 * - 持有 实际的生产者实例 * - 重写 生产者接口的对应函数: 注意不能直接调用被代理对象的成员函数,而是交由 线程调度器统一处理 * - 开放 返回的Future实例 * Created by yhf on 16/12/18. */public class OnPublisherProxy<T> implements OnPublisher<T> { private OnPublisher<T> onPublisher; private Invoker invoker; private Future future; public OnPublisherProxy(OnPublisher<T> onPublisher) { this.onPublisher = onPublisher; } public Future getFuture() { return future; } @Override public void call(OnObserver<T> observer) { String MethodName = "call"; Class parType = OnObserver.class; if (invoker == null) invoker = Invoker.getInstance(); try { Method method = onPublisher.getClass().getMethod(MethodName,parType); //1. 获取 method对应注解 //2. 在对应线程上,调用onPublisher.method(observer) future = invoker.invoke(method,onPublisher, observer); } catch (NoSuchMethodException e) { e.printStackTrace(); } }}
3.【观察者—消费者: 事件的消费者】 的代理
/** * 【观察者---消费者: 事件的消费者】 的代理 * 使每个目标方法通过我们的调度器Invoker调用,而不是直接被调用,OnObserver和OnPublisher必须被代理 * 从而,实现 线程调度 * 否则用户就可以直接调用,没法实现线程调度 * - 实现 消费者的接口---代理模式的基本需求 * - 持有 实际的 <font color= red>消费者们 </font> 实例 * - 重写 消费者接口的对应函数 * 注意1:不能直接调用被代理对象的成员函数,而是交由 线程调度器统一处理 * 注意2:遍历消费者们,代理类是所有消费者的代理,保证生产者.call(消费者)中调用消费者时,所有函数都会被执行 * - 消费者容器的增删查 * Created by yhf on 16/12/18. */public class ObserverProxy<T> implements OnObserver<T>,IObserverProxy<T> { private Vector<OnObserver<T>> observers; private Invoker invoker; public ObserverProxy() { observers = new Vector<OnObserver<T>>(); invoker = Invoker.getInstance(); } @Override public void onSuccess(T t) { String methodName = "onSuccess"; for (OnObserver<T> observer:observers){ try { Method method = observer.getClass().getMethod(methodName,Object.class); invoker.invoke(method,observer,t); } catch (NoSuchMethodException e) { e.printStackTrace(); } } } @Override public void onError(Throwable throwable) { String methodName = "onError"; Class type = Throwable.class; for (OnObserver<T> observer:observers){ try { Method method = observer.getClass().getMethod(methodName,type); invoker.invoke(method,observer,throwable); } catch (NoSuchMethodException e) { e.printStackTrace(); } } } @Override public void onFinished() { String methodName = "onFinished"; for (OnObserver<T> observer:observers){ try { Method method = observer.getClass().getMethod(methodName); invoker.invoke(method,observer); } catch (NoSuchMethodException e) { e.printStackTrace(); } } } @Override public void addObserver(OnObserver<T> observer) { observers.add(observer); } @Override public void rmObserver(OnObserver<T> observer) { observers.remove(observer); } @Override public void clear() { observers.clear(); } @Override public Vector<OnObserver<T>> getObservers() { return observers; }}
4. 线程调度分发器
线程调度模型,是一个比较核心的模块,首先,先放大招:
4.1 线程调度方法
线程调度模型的总入口,注释很详细了,不多赘述了
/** * 根据函数的注解,在不同线程 调用 object执行对应的函数(参数) * @param method 对应生产者|消费者|变换器 传递过来的 即将被调用的 函数 * @param object 对应生产者|消费者|变换器 实例 * @param values 对应函数的参数 * @return */ public Future invoke(Method method, Object object, Object... values){ RunContext runContext = method.getAnnotation(RunContext.class); RunContextType type; int delay = 0; if (runContext == null) type = RunContextType.CurrentThread; else type = runContext.value(); Delay delayAnno = method.getAnnotation(Delay.class); if (delayAnno!=null) delay = delayAnno.value(); Future future = null; switch (type){ case CurrentThread: invoke_current_thread(method,object,delay,values); break; case CurrentLoop: invoke_current_loop(method,object,delay,values); break; case NewThread: invoke_new_thread(method,object,delay,values); break; case MainThread: invoke_main_thread(method,object,delay,values); break; case MainLoop: invoke_main_loop(method,object,delay,values); break; case Calculate: future = invoke_calculate(method,object,delay,values); break; case IO: invoke_io(method,object,delay,values); break; case NewHandlerThread: invoke_new_handler_thread(method,object,delay,values); break; case Dynamic: invoke_dynamic(method, object, values); break; } return future; }
4.2 一种线程调度:NewThread 创建新线程
private void invoke_new_thread(Method method, Object object,int delay,Object... values) { ProxyEntity entity = new ProxyEntity(method,object,values); entity.setDelay(delay); new Thread(entity).start(); }
其中 ProxyEntity 类为封装了数据的Runnable接口,其实invoke_new_thread函数就是 new了一个Runnable,然后start(),这其实就是一个常规线程操作
/** * 封装了数据的Runnable接口 * 一个runnable的简单封装,用于调用产生事件 * Created by yhf on 16/12/18. */public class ProxyEntity implements Runnable{ private Method method; // 动作函数 private Object object;// 动作执行对象 private Object[] args;;//动作函数的参数 private Object ret; private int delay = 0;// 动作的延迟 public ProxyEntity(Method method, Object object, Object... args) { this.method = method; this.object = object; this.args = args; } //设置延迟事件 public void setDelay(int delay) { this.delay = delay; } //执行事件 @Override public void run() { if (delay!=0){ try { Thread.currentThread().sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } } Invoker.invoke_direct(method,object,args); }}
到目前为止,我们已经拿到了 对象+函数+参数,如何实现动态调用 Object的对应Method,并传入参数呢?
4.3 动态调用 对象+函数+参数
- 思路
- 根据 Method对象,拿到 函数名
- 再次做一次 函数 代理模式,根据对应的函数名,switch调用对应的函数方法
public static <T> T invoke_direct(Method method, Object object, Object... values){ //1. 根据 Method对象,拿到 函数名 String name = method.getName(); //2. 再次做一次代理模式,根据对应的函数名,switch调用对应的函数方法 IInvokeDirect invoke = null; if (object instanceof OnObserver){ // 创建对应的代理 // 代理实例持有 实际被代理对象 invoke = new ObserverInvoker(); invoke.setProxy(object); }else if (object instanceof OnPublisher){ invoke = new PublisherInvoker(); invoke.setProxy(object); }else if (object instanceof Func1){ invoke = new Function1Invoker(); invoke.setProxy(object); } if (invoke == null) return null; // 调用代理类的 执行函数 Object ret = invoke.<T>invoke(name,values); if (ret == null) return null; return (T) ret; }
4.3.1 函数代理模式–函数分发模型
函数代理
/** * 函数代理类 * Created by yhf on 16/12/18. */public abstract class IInvokeDirect<T>{ protected T proxy;// 被代理的对象 /** * 设置被代理对象 * @param t */ public void setProxy(T t){ proxy = t; } /** * 根据methodname, 调用被代理类的对应方法 * 函数分发 * @param methodname * @param pars * @param <V> * @return */ public abstract <V> V invoke(String methodname,Object... pars);}
【发布者—被观察者 : 事件的产生者】的函数代理
/** * 【发布者---被观察者 : 事件的产生者】的函数代理 * Created by yhf on 16/12/18. */public class PublisherInvoker extends IInvokeDirect<OnPublisher>{ /** * //调用被代理对象的 call方法产生事件 * 就一个不需要分发 * @param methodname * @param pars * @param <V> * @return */ @Override public <V> V invoke(String methodname, Object... pars) { proxy.call((OnObserver) pars[0]); return null; }}
【观察者—消费者: 事件的消费者】的函数代理
/** * 【观察者---消费者: 事件的消费者】的函数代理 * Created by yhf on 16/12/18. */public class ObserverInvoker extends IInvokeDirect<OnObserver>{ /** * //调用被代理对象的 onSuccess|Error|finish方法产生事件 * @param methodname * @param pars * @param <V> * @return */ @Override public <V> V invoke(String methodname, Object... pars) { V res = null; switch (methodname){ case "onFinished": proxy.onFinished(); break; case "onSuccess": proxy.onSuccess(pars[0]); break; case "onError": proxy.onError((Throwable) pars[0]); break; } return res; }}
5. Test
Publisher.<String>getInstance() .create(new OnPublisher<String>() { @Delay(3*1000) @RunContext(RunContextType.IO) @Override public void call(OnObserver<String> observer) { String res = null; res = httpmodel.dohttp(); if (res!=null) observer.onSuccess(res); else observer.onError(new Throwable("error")); } }) .bind(new OnObserver<String>() { @RunContext(RunContextType.MainThread) @Override public void onSuccess(String s) { resTextView.setText(s); } @RunContext(RunContextType.MainThread) @Override public void onError(Throwable throwable) { Toast.makeText(MainActivity.this,throwable.getMessage(),Toast.LENGTH_LONG).show(); } @Override public void onFinished() { } }) .post();
6. 线程调度的自行实现
一般而言,各自的项目里边应该已经有了自己的线程模型,可以自行设置,在此给出,线程调度器的全部源码:
package test.com.yu.utils.Reactive.impl;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.concurrent.Future;import test.com.yu.utils.Reactive.OnObserver;import test.com.yu.utils.Reactive.OnPublisher;import test.com.yu.utils.Reactive.annotation.Delay;import test.com.yu.utils.Reactive.annotation.RunContext;import test.com.yu.utils.Reactive.entity.Function1Invoker;import test.com.yu.utils.Reactive.entity.IInvokeDirect;import test.com.yu.utils.Reactive.entity.ObserverInvoker;import test.com.yu.utils.Reactive.entity.ProxyEntity;import test.com.yu.utils.Reactive.entity.PublisherInvoker;import test.com.yu.utils.Reactive.entity.RunContextType;import test.com.yu.utils.Reactive.entity.actions.Func1;/** * Created by yhf on 16/12/18. */public class Invoker { private static Invoker invoker; private Handler mainHandler; public final static String DynamicFlagname = "runcontext"; public final static String DynamicFlagDelay = "delay"; public static Invoker getInstance(){ synchronized (Invoker.class){ if (invoker == null) invoker = new Invoker(); } return invoker; } public Invoker() { mainHandler = new Handler(Looper.getMainLooper()); } /** * 根据函数的注解,在不同线程 调用 object执行对应的函数(参数) * @param method 对应生产者|消费者|变换器 传递过来的 即将被调用的 函数 * @param object 对应生产者|消费者|变换器 实例 * @param values 对应函数的参数 * @return */ public Future invoke(Method method, Object object, Object... values){ RunContext runContext = method.getAnnotation(RunContext.class); RunContextType type; int delay = 0; if (runContext == null) type = RunContextType.CurrentThread; else type = runContext.value(); Delay delayAnno = method.getAnnotation(Delay.class); if (delayAnno!=null) delay = delayAnno.value(); Future future = null; switch (type){ case CurrentThread: invoke_current_thread(method,object,delay,values); break; case CurrentLoop: invoke_current_loop(method,object,delay,values); break; case NewThread: invoke_new_thread(method,object,delay,values); break; case MainThread: invoke_main_thread(method,object,delay,values); break; case MainLoop: invoke_main_loop(method,object,delay,values); break; case Calculate: future = invoke_calculate(method,object,delay,values); break; case IO: invoke_io(method,object,delay,values); break; case NewHandlerThread: invoke_new_handler_thread(method,object,delay,values); break; case Dynamic: invoke_dynamic(method, object, values); break; } return future; } private Future invoke_dynamic(Method method, Object object, Object... values) { RunContextType type = null; int delay = 0; try { Field field = object.getClass().getField(DynamicFlagname); type = (RunContextType) field.get(object); Field field1 = object.getClass().getField(DynamicFlagDelay); delay = field1.getInt(object); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if (type == null) return null; Future future = null; switch (type){ case CurrentThread: invoke_current_thread(method,object,delay,values); break; case CurrentLoop: invoke_current_loop(method,object,delay,values); break; case NewThread: invoke_new_thread(method,object,delay,values); break; case MainThread: invoke_main_thread(method,object,delay,values); break; case MainLoop: invoke_main_loop(method,object,delay,values); break; case Calculate: invoke_calculate(method,object,delay,values); break; case IO: invoke_io(method,object,delay,values); break; case NewHandlerThread: invoke_new_handler_thread(method,object,delay,values); break; case Dynamic: invoke_dynamic(method, object, values); break; } return future; } private void invoke_new_handler_thread(Method method, Object object,int delay,Object... values) { ProxyEntity entity = new ProxyEntity(method,object,values); HandlerThread thread = new HandlerThread(object.getClass().getName()+method.getName()); thread.start(); Handler handler = new Handler(thread.getLooper()); if (delay == 0) handler.post(entity); else handler.postDelayed(entity,delay); } private void invoke_io(Method method, Object object,int delay,Object... values) { ProxyEntity entity = new ProxyEntity(method,object,values); entity.setDelay(delay); //MySigleThreadQueue.AddTask(entity); } private Future invoke_calculate(Method method, Object object,int delay,Object... values) { ProxyEntity entity = new ProxyEntity(method,object,values); entity.setDelay(delay); //return MyWorkThreadQueue.AddTask(entity); return null; } private void invoke_new_thread(Method method, Object object,int delay,Object... values) { ProxyEntity entity = new ProxyEntity(method,object,values); entity.setDelay(delay); new Thread(entity).start(); } private void invoke_main_thread(Method method, Object object,int delay,Object... values) { Looper mianLoop = Looper.getMainLooper(); ProxyEntity entity = new ProxyEntity(method,object,values); if (Looper.myLooper() != Looper.getMainLooper()){ invoke_main_loop(method, object,delay,values); }else { invoke_current_thread(method, object, delay, values); } } private void invoke_main_loop(Method method, Object object,int delay,Object... values) { ProxyEntity entity = new ProxyEntity(method,object,values); if (delay == 0) mainHandler.post(entity); else mainHandler.postDelayed(entity,delay); } private void invoke_current_loop(Method method, Object object,int delay, Object... values) { Looper looper = Looper.myLooper(); if (looper == null) throw new RuntimeException(Thread.currentThread().getName()+"不是HandlerThread"); Handler handler = new Handler(looper); ProxyEntity entity = new ProxyEntity(method,object,values); if (delay == 0) handler.post(entity); else handler.postDelayed(entity,delay); } private <T> T invoke_current_thread(Method method, Object object,int delay,Object... values) { if (delay!=0) { try { Thread.currentThread().sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } } return invoke_direct(method, object, values); } public static <T> T invoke_direct(Method method, Object object, Object... values){ //1. 根据 Method对象,拿到 函数名 String name = method.getName(); //2. 再次做一次代理模式,根据对应的函数名,switch调用对应的函数方法 IInvokeDirect invoke = null; if (object instanceof OnObserver){ // 创建对应的代理 // 代理实例持有 实际被代理对象 invoke = new ObserverInvoker(); invoke.setProxy(object); }else if (object instanceof OnPublisher){ // 创建对应的代理 // 代理实例持有 实际被代理对象 invoke = new PublisherInvoker(); invoke.setProxy(object); }else if (object instanceof Func1){ // 创建对应的代理 // 代理实例持有 实际被代理对象 invoke = new Function1Invoker(); invoke.setProxy(object); } if (invoke == null) return null; Object ret = invoke.<T>invoke(name,values); if (ret == null) return null; return (T) ret; }}
- (4.6.22.2)来吧,是时候撸一份自己的RxJava框架啦:代理模式实现线程调度
- (4.6.22.1)来吧,是时候撸一份自己的RxJava框架啦:观察者模式实现链式调用
- (4.6.22)来吧,是时候撸一份自己的RxJava框架啦
- (4.6.22.4)来吧,是时候撸一份自己的RxJava框架啦:残缺消费者的实现
- (4.6.22.3)来吧,是时候撸一份自己的RxJava框架啦:装饰器模式实现操作符顺序调用
- (4.6.22.5)来吧,是时候撸一份自己的RxJava框架啦:强撸为eventbus
- Rxjava的线程调度
- RxJava 2.0来啦!
- RxJava 2.0来啦!
- 在Android上打造属于自己的Rxjava框架(二)调度器
- rxjava线程调度的正确使用姿势
- 是时候把自己想法写出来
- RxJava 和 RxAndroid 五(线程调度)
- RxJava 和 RxAndroid 五(线程调度)
- RxJava 和 RxAndroid 五(线程调度)
- RxJava 和 RxAndroid 五(线程调度)
- RxJava 和 RxAndroid 五(线程调度)
- RxJava 和 RxAndroid 五(线程调度)
- mysql和oracle的一个汉字占几个字符?
- 第十七节,class
- 服务不支持chkconfig解决方法脚本
- Window VMware MAC OS 安装
- 如何通过安装包安装应用到手机
- (4.6.22.2)来吧,是时候撸一份自己的RxJava框架啦:代理模式实现线程调度
- 网页刷新或者重新加载后滚动条的位置不变
- fastClick入坑爬坑详解
- 货币金额转化大写
- 通信死时间以及缓冲队列的使用对系统死时间的影响
- 第十八节,修饰器
- rpm 解压和查看清单
- .net core中有哪些被抛弃的类
- 在oracle里如何将String转换成Date?????