(4.6.22.2)来吧,是时候撸一份自己的RxJava框架啦:代理模式实现线程调度

看了上篇(4.6.22.1)来吧,是时候撸一份自己的RxJava框架啦:观察者模式实现链式调用有木有觉得,线式调用很简单呢?

那么,重头戏来了,我们如何实现线程调度?

就是要借助代理模式,代理模式不懂的话,请转向(2.2.1)设计模式一览系列文章

线程调度的原理: 代理模式。
2.1 所有类的成员函数的调用都不是直接由对应对象实例调用,而是由代理类去调用
2.2 通用的总代理类,实现线程调度

设计思路图

在(4.6.22.1)的模式中,我们是直接调用 生产者.call()函数,和 消费者.onSuccess()函数,直接调用那么自然意味着不会有线程调度的时机了
|
不能直接调用 生产者|消费者的对应成员方法,不调用?
|
使用代理模式,做分别的代理类,代理类根据对应的函数注解,在不同的线程执行被代理类对象的成员函数
|
优化空间? 线程的调度模型应该是一样,应该做一个统一的调度模型,实现消费者or生产者的调度是通过同一种调度模型实现
|
那就是搞一个 线程调度分发器喽

一句话:使每个对象的成员方法通过我们的调度器Invoker调用,而不是直接被调用

设计思路

  • 核心的业务控制器

  • 【发布者—被观察者 : 事件的产生者】 的代理

    • 实现 生产者的接口—代理模式的基本需求
    • 持有 实际的生产者实例
    • 重写 生产者接口的对应函数: 注意不能直接调用被代理对象的成员函数,而是交由 线程调度器统一处理
    • 开放 返回的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;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值