Active Object 模式

将接口的方法实现异步执行 结合Future(凭证)模式,流水线模式,代理模式等结合使用。

一般代码编写

  1. 编写接口方法类和实现类
/**
 * 方法接口命名
 */
public interface OrderService {
    // 有返回参数的 异步操作只能先返回凭据信息给调用者  通过id查找订单信息
    Future<String> findOrderDetils(long orderId);
    // 没有返回值  提交订单
    void order(String account,long orderId);
 }


/**
 * 实现类 模拟方法业务执行
 */
public class OrderServiceImpl implements OrderService{

    @Override
    public Future<String> findOrderDetils(long orderId) {
        return FutureService.<Long,String>newService().submit(input -> {
            try {
                TimeUnit.SECONDS.sleep(4);
                System.out.println("获取订单信息中......... 信息为:"+orderId);
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }
            return "1234qwer";
        },orderId,null);
    }

    @Override
    public void order(String account, long orderId) {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println("提交订单中........信息为: "+account+","+orderId);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
  1. 编写接口方法代理类和生成代理类的工厂类 将接口方法封装成流水线模式中对应的待加工产品
/**
 * 接口使用代理类
 * 将接口的每个方法封装成MethodMessage 然后交给ActiveMessage队列执行
 */
public class OrderServiceProxy implements OrderService {
    private final OrderService orderService;

    private final MethodMessageQueue methodMessageQueue;

    public OrderServiceProxy(OrderService orderService, MethodMessageQueue methodMessageQueue) {
        this.orderService = orderService;
        this.methodMessageQueue = methodMessageQueue;
    }

    @Override
    public Future<String> findOrderDetils(long orderId) {
        // 定义一个可以立刻返回的凭证
        final ActiveFuture<String> activeFuture = new ActiveFuture<>();
        // 收集方法参数信息 和返回值信息 封装成对应方法的MethodMessage
        Map<String,Object> params = new HashMap<>();
        params.put("orderId",orderId);
        params.put("activeFuture",activeFuture);
        MethodMessage message = new MethodMessageFind(params,orderService);
        // 将待加工的信息放进传送带
        methodMessageQueue.offer(message);
        return activeFuture;
    }

    @Override
    public void order(String account, long orderId) {
        // 收集参数
        Map<String,Object> params = new HashMap<>();
        params.put("account",account);
        params.put("orderId",orderId);
        MethodMessage message = new MethodMessageOrder(params,orderService);
        // 放入传送带
        methodMessageQueue.offer(message);
    }
}



/**
 * 代理工厂类
 */
public final class OrderServiceFactory {
    // 用static修饰 保证JVM进程唯一
    private final static MethodMessageQueue activeQueue = new MethodMessageQueue();
    // 去除new方法
    private OrderServiceFactory(){}
    // 返回OrderService接口
    public static OrderService toActiveObject(OrderService orderService){
        return new OrderServiceProxy(orderService,activeQueue);
    }
}
  1. 编写待加工产品的接口类 和对应接口方法封装的类型
/**
 * 收集每个接口的方法参数
 * 类似 流水线设计模式中的半产品信息 其中execute方法相当加工方法
 */
public abstract class MethodMessage {
    // 收集的方法参数 返回future类型数据一样收集
    protected final Map<String,Object> params;

    protected final OrderService orderService;

    protected MethodMessage(Map<String, Object> params, OrderService orderService) {
        this.params = params;
        this.orderService = orderService;
    }
    // execute方法 加工方法
    public abstract void execute();
}


/**
 * findOrderDetils 方法的接口封装类
 */
public class MethodMessageFind extends MethodMessage{

    public MethodMessageFind(Map<String,Object> params,OrderService orderService){
        super(params,orderService);
    }

    @Override
    public void execute() {
        // 设置方法的参数信息 获取方法执行后凭证信息
        Future<String> realFuture = orderService.findOrderDetils((long) params.get("orderId"));
        ActiveFuture<String> activeFuture = (ActiveFuture<String>) params.get("activeFuture");
        try {
            // 通过凭证获取结果并设置结果
            String result = realFuture.get();
            activeFuture.finish(result);
        } catch (InterruptedException e) {
            // 异常设置空值
            activeFuture.finish(null);
        }
    }
}


/**
 * order 提交方法的封装类
 */
public class MethodMessageOrder extends MethodMessage{

    public MethodMessageOrder(Map<String,Object> params,OrderService orderService){
        super(params, orderService);
    }
    @Override
    public void execute() {
        // 获取方法参数 执行对应方法
        orderService.order((String) params.get("account"),(Long) params.get("orderId"));
    }
}


/**
 * 返回凭据
 * @param <T>
 */
public class ActiveFuture<T> extends FutureTask<T> {
    // 将方法权限 改大 由protected 改成 public  方便调用
    @Override
    public void finish(T result) {
        super.finish(result);
    }
}
  1. 编写流水线模式的对应传送带类和对应的加工工人类
/**
 * 类似 流水线模式的传送带 将proxy传过来的MethodMessage  开辟线程执行掉
 */
public class MethodMessageQueue {
    // 用于存放提交的MethodMessage信息
    private final LinkedList<MethodMessage> messages = new LinkedList<>();

    public MethodMessageQueue(){
        // 启动线程
        new MethodDaemonThread(this).start();
    }

    // 添加
    public void offer(MethodMessage methodMessage){
        synchronized (this){
            messages.addLast(methodMessage);
            // 这里只设置一个线程执行任务
            this.notify();
        }
    }
    // 弹出
    protected MethodMessage take(){
        synchronized (this){
            // queue没有MethodMessage时 挂起阻塞
            while (messages.isEmpty()){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            // 有MethodMessage 则弹出第一个
            return messages.removeFirst();
        }
    }
}



/**
 * 用于执行ActiveMessageQueue 上的MethodMessage execute方法
 */
public class MethodDaemonThread extends Thread{
    private final MethodMessageQueue queue;

    public MethodDaemonThread(MethodMessageQueue queue) {
        super("MethodDaemonThread");
        this.queue = queue;
        setDaemon(true);
    }

    @Override
    public void run() {
        while (true){
            // 执行待加工产品的加工方法
            MethodMessage methodMessage = this.queue.take();
            methodMessage.execute();
        }
    }
}
  1. 测试
public static void main(String[] args) throws InterruptedException {
        OrderService orderService = OrderServiceFactory.toActiveObject(new OrderServiceImpl());
        orderService.order("测试1133",121212);

        System.out.println(" 是否继续执行下面的代码 ");
        //Thread.currentThread().join();
        Future<String> future = orderService.findOrderDetils(131313);
        String result = future.get();
        System.out.println("加工结果:"+result);
        System.out.println("---------------------------------------------------");
}

结果: 实现接口方法的异步执行操作

 是否继续执行下面的代码 
提交订单中........信息为: 测试1133,121212
获取订单信息中......... 信息为:131313
加工结果:1234qwer
---------------------------------------------------

使用动态代理的方式生成接口方法封装类

因为上面的方式决定新添加一个接口方法就会有一个新的接口封装类,所以优化成使用动态代理的方式生成接口封装类。

  1. 动态代理方式的接口方法封装类
/**
 * 使用MethodMessage封装 方法的参数和返回值  每一个方法都要写对应的MethodMessage封装类
 * 所以进一步优化 使用动态代理来实现 一次性解决方法
 * 这个类和MethodMessage一样是用来收集 方法参数和返回值信息的
 */
// 包可见 只在框架中使用
class ActiveMessage {
    // 接口方法参数
    private final Object[] params;
    // 接口方法
    private final Method method;
    // 接口返回值类型
    private final ActiveFuture<Object> future;
    // 具体的Service接口
    private final Object service;

    private ActiveMessage(Builder builder){
        this.params = builder.params;
        this.method = builder.method;
        this.service = builder.service;
        this.future = builder.future;
    }

    //通过反射方法调用其对应方法
    public void execute(){
        try {
            // 执行接口方法
            Object result = method.invoke(service, params);
            if (future != null){
                // 凭证不为空 要根据凭证获取真实结果  并将结果设置进对应执行线程中
                Future<?> realFuture = (Future<?>) result;
                Object realResult = realFuture.get();
                future.finish(realResult);
            }
        }catch (Exception e){
            // 发生异常 有凭证的设置null 没有凭证不处理
            if(future != null){
                future.finish(null);
            }
        }
    }


    // Builder 负责ActiveMessage的构造 一种典型的 Gof Builder 设计模式
    static class Builder{
        private Object[] params;
        private Method method;
        private ActiveFuture<Object> future;
        private Object service;
        // 构造方法传入 接口方法参数 的构造
        public Builder useMethod(Method method){
            this.method = method;
            return this;
        }
        // 传入返回值的构造
        public Builder useFuture(ActiveFuture<Object> future){
            this.future = future;
            return this;
        }
        // 传入方法参数的构造
        public Builder useParams(Object[] params){
            this.params = params;
            return this;
        }
        // 传入Service接口的构造
        public Builder useService(Object service){
            this.service = service;
            return this;
        }
        // 构造ActiveMessage实例
        public ActiveMessage build(){
            return new ActiveMessage(this);
        }
    }
}
  1. 生成代理的工厂类,自定义异常(和系统异常区分开),自定义注解(标注哪些方法使用异步处理)
/**
 * 负责生成Service接口的代理 和构建ActiveMessage
 */
public class ActiveServiceFactory {
    // 设置存放ActiveMessage的集合
    private final static ActiveMessageQueue queue = new ActiveMessageQueue();

    // 生成Service的代理类
    public static <T> T active(T instance){
        Object proxy = Proxy.newProxyInstance(instance.getClass().getClassLoader(),
                instance.getClass().getInterfaces(),new ActiveInvocationHandler<>(instance));
        return (T) proxy;
    }

    // ActiveInvocationHandler 是InvocationHandler的子类 生成代理类要用的
    private static class ActiveInvocationHandler<T> implements InvocationHandler{

        // 传入的Service接口
        private final T instance;
        ActiveInvocationHandler(T instance){
            this.instance = instance;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 如果接口方法被@ActiveMethod自定义注解标记 则转化成ActiveMessage放到传送带上执行
            if(method.isAnnotationPresent(ActiveMethod.class)){
                // 检测该方法是否符合规范
                this.checkMethod(method);
                ActiveMessage.Builder builder = new ActiveMessage.Builder();
                builder.useMethod(method).useParams(args).useService(instance);
                Object result = null;
                // 检测方法返回是否为凭证类型
                if (this.isReturnFutureType(method)){
                    // 设置凭证信息
                    result = new ActiveFuture<>();
                    builder.useFuture((ActiveFuture<Object>) result);
                }
                // 放进传送带
                queue.offer(builder.build());
                return result;
            }else {
                // 普通方法正常执行
                return method.invoke(instance,args);
            }
        }
        // 检查方法返回值类型是否为 Future.class
        private boolean isReturnFutureType(Method method) {
            return method.getReturnType().isAssignableFrom(Future.class);
        }

        // 检查返回值类型是否是 ActiveFuture 类型
        private void checkMethod(Method method) throws IllegalActiveMethod {
            if (!method.getReturnType().equals(Void.TYPE) &&
                !isReturnFutureType(method)){
                throw new IllegalActiveMethod(method.getName()+" 该方法的返回值类型不对");
            }
        }


    }

}


/**
 * 自定义方法转化失败异常
 */
public class IllegalActiveMethod extends Exception{
    public IllegalActiveMethod(String message){
        super(message);
    }
}



/**
 * 自定义注解标记 哪个方法需要 使用ActiveMessage封装 放到传送带上执行
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ActiveMethod {
}
  1. 将流水线模式的传送带和加工工人改造一下,把待加工产品改成动态代理的接口方法封装类
/**
 * 传送带 用于存放ActiveMessage 并开辟线程执行对应方法
 */
public class ActiveMessageQueue {
    // 存放ActiveMessage集合
    private final LinkedList<ActiveMessage> queue = new LinkedList<>();

    public ActiveMessageQueue(){
        new ActiveDaemonThread(this).start();
    }

    // 添加
    public void offer(ActiveMessage message){
        synchronized (this){
            queue.addLast(message);
            this.notify();
        }
    }
    // 弹出
    protected ActiveMessage take(){
        synchronized (this){
            while (queue.isEmpty()){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            return queue.removeFirst();
        }
    }
}


/**
 * 动态代理的执行线程
 */
public class ActiveDaemonThread extends Thread{
    private final ActiveMessageQueue queue;

    public ActiveDaemonThread(ActiveMessageQueue queue) {
        super("ActiveThread");
        this.queue = queue;
        // 设置线程名称 和守护线程
        setDaemon(true);
    }

    @Override
    public void run() {
        while (true){
            ActiveMessage message = this.queue.take();
            message.execute();
        }
    }
}
  1. 测试
public interface OrderService {

    // 有返回参数的 异步操作只能先返回凭据信息给调用者  通过id查找订单信息
    Future<String> findOrderDetils(long orderId);
    // 没有返回值  提交订单
    void order(String account,long orderId);
   
    // 动态代理的方式实现
    @ActiveMethod
    default Future<String> getOrder(Long orderId) {
        return FutureService.<Long,String>newService().submit(input -> {
            try {
                TimeUnit.SECONDS.sleep(4);
                System.out.println("动态代理方式获取订单信息中......... 信息为:"+orderId);
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }
            return "qwer1234";
        },orderId,null);
    }

    @ActiveMethod
    default void setOrder(String name,String orderNo){
        System.out.println("动态代理方式提交订单中........信息为: "+name+","+orderNo);
    }
}



public static void main(String[] args) throws InterruptedException {
        System.out.println("---------------------------------------------------");
        // 动态代理方式
        OrderService orderService = ActiveServiceFactory.active(new OrderServiceImpl());
        orderService.setOrder("订单名称12","订单编号123");

        System.out.println(" 动态代理方式 是否继续执行下面的代码 ");
        Future<String> future2 = orderService.getOrder(1234L);
        String result2 = future2.get();
        System.out.println("动态代理方式 加工结果:"+result2);
    }

执行结果: 接口方法实现异步执行
---------------------------------------------------
 动态代理方式 是否继续执行下面的代码 
动态代理方式提交订单中........信息为: 订单名称12,订单编号123
动态代理方式获取订单信息中......... 信息为:1234
动态代理方式 加工结果:qwer1234