前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >并行执行任务思考

并行执行任务思考

作者头像
LiosWong
发布于 2018-10-29 09:42:36
发布于 2018-10-29 09:42:36
52400
代码可运行
举报
文章被收录于专栏:后端沉思录后端沉思录
运行总次数:0
代码可运行

问题

这篇文章由之前的并行执行任务发展而来,如何生成task,在之前的文章中,生成task方式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Abstract Task: 
public abstract class BasicUserFilter implements Callable<UserFilterDto> {
private static final Log logger = LogFactory.getLog(BasicUserFilter.class);
@Autowired
UserService userService;
public Long companyId;
public Long userId;
@Override
public UserFilterDto call() throws Exception {
    try {
        //每个执行任务调用同一个方法,只是入参不同
        Response<Boolean> response = userService.filter(getUserId(), getCompanyId());
        if (response.isSuccess() && response.getResult()) {
            return new UserFilterDto().setCompanyId(getCompanyId()).setUserId(getUserId()).setFilterResultEnum(FilterResultEnum.TRUE);
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return new UserFilterDto().setCompanyId(getCompanyId()).setUserId(getUserId()).setFilterResultEnum(FilterResultEnum.FALSE);
}
@PostConstruct
abstract void init();
// ... 篇幅关系,省略属性setter、getter方法
}
}

Task1:
public class Task1 extends BasicUserFilter{
    @Override
    public void init() {
        FilterConfigManager.register(CompanyAppIdEnum.GEI_NI_HUA.getCompanyId(),this);
    }
    @Override
    public UserFilterDto call() throws Exception {
        return super.call();
    }
}

上面生成任务类时,使用了策略模式,添加每一个任务都必须新增一个实体类,且实现BasicUserFilter或者重写自己的 call方法,有木有比较好的方法解决这种繁琐的任务类构建呢。

方案

解决切入点,就是所有的任务类都执行了相同的逻辑,且调用了入参不同的方法而已,无疑使用代理模式去动态生成任务类,思路有了,代码实现也边的简单起来。下面使用java InvocationHandler创建动态代理类.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ProxyHandler:
/**
 * @author LiosWong
 * @description
 * @date 2018/10/27 上午1:10
 */
public class ProxyHandler<T> implements InvocationHandler, Serializable {
    private static final long serialVersionUID = -6424540398559729838L;
    private final ProxyInterface<T> proxyInterface;

    public ProxyHandler(ProxyInterface<T> proxyInterface) {
        this.proxyInterface = proxyInterface;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 根据方法名,执行不同逻辑
        if ("call".equals(method.getName())) {
            return proxyInterface.call();
        }
        return null;
    }
}
ProxyInterface:为了使代理模版通用,添加接口约束
/** 
 * @author LiosWong
 * @description 可扩展代理接入点
 * @date 2018/10/27 上午1:11
 */
public interface ProxyInterface<T> extends Callable<T> {

}
ProxyFactory:代理工厂
public class ProxyFactory<T> {
private final Class<T> mapperInterface;

public ProxyFactory(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
    return mapperInterface;
}
@SuppressWarnings("unchecked")
protected T newInstance(ProxyHandler<T> mapperProxy) {
    return (T) java.lang.reflect.Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
public T newInstance(ProxyInterface proxyInterface) {
    final ProxyHandler<T> mapperProxy = new ProxyHandler<T>(proxyInterface);
    return newInstance(mapperProxy);
}
}

完成了上面的动态代理类构建,下面就是在业务代码中使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ProxyFactory proxyFactory = new ProxyFactory<Callable>(Callable.class);
        List<Callable<UserFilterDto>> callableList = new ArrayList<>();
        List<UserFilterDto> filterDtosResult = new ArrayList<>();
        // 动态生成代理类
        list.forEach(p -> {
            Callable<UserFilterDto> callable = null;
            // 复用代理模版
            switch (concurrencyType) {
                case FILTER:
                    callable = (Callable<UserFilterDto>) proxyFactory.newInstance(new ProxyFilterCallable(xjUserService, userId, p.getCompanyId()));
                    break;
                case SATISFY:
                    callable = (Callable<UserFilterDto>) proxyFactory.newInstance(new ProxySatisfyCallable(companyUserGroupService, userId, p.getCompanyId()));
                    break;
                default:
                    break;
            }
            callableList.add(callable);
        });

ProxyFilterCallable:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ProxyFilterCallable<T> implements ProxyInterface<T> {
    private static final Log logger = LogFactory.getLog(ProxyFilterCallable.class);
    private UserService userService;
    private Long userId;
    private Long companyId;

    public ProxyFilterCallable(XjUserService xjUserService, Long userId, Long companyId) {
        this.xjUserService = xjUserService;
        this.userId = userId;
        this.companyId = companyId;
    }
    @Override
    public T call() throws Exception {
        try {
            Response<Boolean> response = userService.filter(getUserId(), getCompanyId());
            if (response.isSuccess() && response.getResult()) {
                return (T) new UserFilterDto().setCompanyId(getCompanyId()).setUserId(getUserId()).setFilterResultEnum(FilterResultEnum.TRUE);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return (T) new UserFilterDto().setCompanyId(getCompanyId()).setUserId(getUserId()).setFilterResultEnum(FilterResultEnum.FALSE);
    }
    // ...
}

ProxySatisfyCallable:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ProxySatisfyCallable<T> implements ProxyInterface<T> {
    private static final Log logger = LogFactory.getLog(ProxyFilterCallable.class);
    private CompanyUserGroupService companyUserGroupService;
    private Long userId;
    private Long companyId;

    public ProxySatisfyCallable(CompanyUserGroupService companyUserGroupService, Long userId, Long companyId) {
        this.companyUserGroupService = companyUserGroupService;
        this.userId = userId;
        this.companyId = companyId;
    }

    @Override
    public T call() throws Exception {
        try {
            XjFilterUserResultVo xjFilterUserResultVo = companyUserGroupService.checkUserInfoIsSatisfyCompany(getUserId(), getCompanyId());
            if (Objects.nonNull(xjFilterUserResultVo) && xjFilterUserResultVo.getResult()) {
                return (T) new UserFilterDto().setCompanyId(getCompanyId()).setUserId(getUserId()).setFilterResultEnum(FilterResultEnum.TRUE);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return (T) new UserFilterDto().setCompanyId(getCompanyId()).setUserId(getUserId()).setFilterResultEnum(FilterResultEnum.FALSE);
    }
    // ...
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端沉思录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
spring shiro权限控制_shiro权限管理流程
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说spring shiro权限控制_shiro权限管理流程,希望能够帮助大家进步!!!
Java架构师必看
2022/08/14
1.9K0
spring shiro权限控制_shiro权限管理流程
源码分析(1.4万字) | Mybatis接口没有实现类为什么可以执行增删改查
MyBatis 是一款非常优秀的持久层框架,相对于IBatis更是精进了不少。与此同时它还提供了很多的扩展点,比如最常用的插件;语言驱动器,执行器,对象工厂,对象包装器工厂等等都可以扩展。那么,如果想成为一个有深度的男人(程序猿),还是应该好好的学习一下这款开源框架的源码,以此可以更好的领会设计模式的精髓(面试?)。其实可能平常的业务开发中,并不会去深究各个框架的源代码,也常常会听到即使不会也可以开发代码。但!每个人的目标不同,就像;代码写的好工资加的少(没有bug怎么看出你工作嘞!),好!为了改变世界,开始分析喽!
小傅哥
2020/07/14
1K0
源码分析(1.4万字) | Mybatis接口没有实现类为什么可以执行增删改查
深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
在前九篇中,介绍了mybatis的配置以及使用, 那么本篇将走进mybatis的源码,分析mybatis 的执行流程, 好啦,鄙人不喜欢口水话,还是直接上干活吧:
须臾之余
2019/07/05
5890
深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
2021年了,该懂Mybatis是怎么实现的了!
想要实现一套增删改查是一件极其简单的事情,让人困惑的是UserMapper是一个接口,为什么可以被注入到UserService中,为什么调用UserMapper接口中的方法就可以执行想要执行的SQL,从而完成我们想要的结果。
java进阶架构师
2021/01/05
7270
MyBatis系列之浅谈SQL执行流程分析
这篇文章主要以分析Mybatis框架执行SQL的流程。 回忆曾经独立使用Mybatis半自动化框架时,我们需要执行以下步骤:
沁溪源
2020/09/03
4330
美团面试:为什么就能直接调用userMapper接口的方法?
老规矩,先上案例代码,这样大家可以更加熟悉是如何使用的,看过Mybatis系列的小伙伴,对这段代码差不多都可以背下来了。
田维常
2020/12/31
6060
美团面试:为什么就能直接调用userMapper接口的方法?
MyBatis源码阅读(五) ---Mapper接口的获取过程
前面一篇文章我们总结了SqlSession的创建过程,既然会话已经创建成功,那么下一步自然就是去获取到Mapper接口执行具体的SQL,当然也可以直接使用SqlSession执行具体的SQL。本篇文章主要分析一下Mapper接口的获取过程。
终有救赎
2023/12/26
3330
MyBatis源码阅读(五) ---Mapper接口的获取过程
MyBatis源码解析之基础模块—binding
上述两份源码就是使用ibatis开发的dao,从中可以看出dao实现类其实没有什么业务逻辑处理,就是为了绑定namespace 及sql节点。
todobugs
2020/10/27
8660
MyBatis的SQL执行过程
首先我们来看看mapper 接口的代理类的生成过程,如下是一个MyBatis查询的调用实例。
码农飞哥
2021/08/18
5750
设计模式在MyBatis中体现
我们都知道3类23中设计模式,但是大多数停留在概念上面,很抽象,不知道我们写代码过程中哪些地方运行了哪些设计模式,今天我们来看看MyBatis中运用了哪些设计模式
小熊学Java
2023/07/16
1600
设计模式在MyBatis中体现
聊聊Mybatis的实现原理
平时我们使用的一般是集成了Spring或是Spring Boot的Mybatis,封装了一层,看源码不直接;如下,看看原生的Mybatis使用示例
Ryan_OVO
2023/10/19
1730
聊聊Mybatis的实现原理
[ORM] MyBatis 中是如何运用的代理模式的?
本文主要介绍设计模式之代理模式,并分析代理模式在 Mybatis 中是如何使用的?
架构探险之道
2020/05/29
9640
[ORM] MyBatis 中是如何运用的代理模式的?
从 Spring 集成 MyBatis 到浅析 Java 动态代理
因为 MyBatis 的易上手性和可控性,使得它成为了 ORM框架中的首选。近日新起了一个项目,所以重新搭建了一下 Spring-mybatis, 下面是搭建笔记和从 Spring-mybatis源码分析其如何使用 Java动态代理,希望对大家有帮助。
Java技术江湖
2019/09/24
4650
从 Spring 集成 MyBatis 到浅析 Java 动态代理
MyBatis 使用的 9 种设计模式,真是太有用了~
虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。
好好学java
2019/05/15
5000
MyBatis 使用的 9 种设计模式,真是太有用了~
MyBatis源码解读(2)——MapperProxy
SqlSession可以说是整个MyBatis的重中之重,在SqlSession中涉及到前一篇四大对象:Executor、StatementHandler、ParameterHandler、ResultHandler,所以在此先只对SqlSession有一个大概的了解。 在代码中我们可以看到当我们构造出一个SqlSession实例过后,可以通过SqlSession构造出Mappper映射器。UserMapper是一个接口,那么我们可以肯定的是,它一定是用了Java的动态代理生成了一个代理类。 SqlSess
用户1148394
2018/01/09
1.1K0
MyBatis源码解读(2)——MapperProxy
Mybatis源码分析之Mapper注册与绑定
Mybatis 是一个「面向 sql」的持久层框架,它可实现动态拼装 sql,极其灵活,同时避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集,其插件机制允许在已映射语句执行过程中的某一点进行拦截调用等等,让我忍不住想要撸一撸它的源码。
张乘辉
2019/06/14
1.1K0
带你彻底搞懂MyBatis的底层实现之binding模块
  基础支持层位于MyBatis整体架构的最底层,支撑着MyBatis的核心处理层,是整个框架的基石。基础支持层中封装了多个较为通用的、独立的模块。不仅仅为MyBatis提供基础支撑,也可以在合适的场景中直接复用。
用户4919348
2021/06/01
6500
带你彻底搞懂MyBatis的底层实现之binding模块
从 Spring 集成 MyBatis 到浅析 Java 动态代理
因为 MyBatis 的易上手性和可控性,使得它成为了 ORM框架中的首选。近日新起了一个项目,所以重新搭建了一下 Spring-mybatis, 下面是搭建笔记和从 Spring-mybatis源码分析其如何使用 Java动态代理,希望对大家有帮助。
Bug开发工程师
2019/06/03
5360
『手写Mybatis』创建简单的映射器代理工厂
在阅读本文之前,我相信你已经是一个 Mybatis ORM 框架工具使用的熟练工了,那你是否清楚这个 ORM 框架是怎么屏蔽我们对数据库操作的细节的?
程序员NEO
2024/05/12
551
『手写Mybatis』创建简单的映射器代理工厂
浅析MyBatis的动态代理原理[通俗易懂]
前言 一直以来都在使用MyBatis做持久化框架,也知道当我们定义XXXMapper接口类并利用它来做CRUD操作时,Mybatis是利用了动态代理的技术帮我们生成代理类。那么动态代理内部的实现细节到底是怎么的呀?XXXMapper.java类和XXXMapper.xml到底是如何关联起来的呀?本篇文章就来详细剖析下MyBatis的动态代理的具体实现机制。
全栈程序员站长
2022/09/22
2K0
推荐阅读
相关推荐
spring shiro权限控制_shiro权限管理流程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档