看了上篇(4.6.22.1)来吧,是时候撸一份自己的RxJava框架啦:观察者模式实现链式调用有木有觉得,线式调用很简单呢?
那么,重头戏来了,我们如何实现线程调度?
就是要借助代理模式,代理模式不懂的话,请转向(2.2.1)设计模式一览系列文章
线程调度的原理: 代理模式。
2.1 所有类的成员函数的调用都不是直接由对应对象实例调用,而是由代理类去调用
2.2 通用的总代理类,实现线程调度
设计思路图
在(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;
}
}