(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 函数代理模式函数分发模型
          • 函数代理
          • 发布者被观察者 事件的产生者的函数代理
          • 观察者消费者 事件的消费者的函数代理
    • 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实例
  • 【观察者—消费者: 事件的消费者】 的代理

    • 实现 消费者的接口—代理模式的基本需求
    • 持有 实际的 消费者们 实例
    • 重写 消费者接口的对应函数
      注意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
原创粉丝点击