后台自定义统一任务查询框架

背景

项目中有很多地方存在如下业务逻辑:

从数据库中查询多条数据并构成旧集合,然后遍历旧集合,处理每条数据,将返回的新元素并加入新集合。

目前实现该逻辑的方式是,采用线程池并借助CountDownLatch
核心代码如下:

//新集合
List<OperatorProcessVO> vos = Collections.synchronizedList(new ArrayList<>());
//数据库记录
CountDownLatch latch = new CountDownLatch(operatorProcesses.size());
try {
    for (OperatorProcess operatorProcess : operatorProcesses) {
    	//线程池
        executorService.submit(()->{
            try {
            	//业务处理
 	    	    ......
     	  		......
     	  		//得到新元素vo,并加入新集合
       	         vos.add(vo);
            }catch (Exception e){
                log.error("xxx", e);
            }
            finally {
                latch.countDown();
            }
        });
    }
    //等待
    latch.await();
} catch (Exception e) {
    log.error("xxx", e);
}

当前存在的问题是,项目中有很多地方都有这样的处理,导致出现了大量重复的代码,加大了后期维护成本。
因此,希望有一种统一的框架来将上述逻辑封装,而不是重复造轮子。

实现方案

1.提交任务入口

首先,定义任务提交类TaskExecuteFramework,其中的submitTask方法用于提交任务。如下

@Component
@Slf4j
public class TaskExecuteFramework {
	//线程池
    private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);

    public <OLD,NEW,ADDITIONAL> List<NEW> submitTask(List<OLD> oldList, TaskProcessor<NEW, OLD> taskProcessor, ADDITIONAL additional){
        CountDownLatch latch = new CountDownLatch(oldList.size());
        //新集合
        List<NEW> newList = Collections.synchronizedList(new ArrayList<>());
        try {
            for (OLD old : oldList) {
                executorService.submit(()->{
                    try {
                        if(additional != null){
                            ThreadLocalInfoUtil.setValue("additionalParam", additional);
                        }
                        //处理业务数据
                        NEW n = taskProcessor.handTask(old);
                        //加入新集合
                        if(newList != null){
                            Optional
                                    .ofNullable(n)
                                    .ifPresent(entity->{
                                        newList.add(entity);
                                    });
                        }
                    }catch (Exception e){
                        log.error("handTask error", e);
                    }finally {
                        latch.countDown();
                        ThreadLocalInfoUtil.remove();
                    }
                });
            }
            latch.await();
        }catch (Exception e){
            log.error("submitTask error", e);
        }
        return newList;
    }

}

该方法的核心逻辑相比之前没有变化,不同点在于:

首先,由于需要处理不同类型的业务,所以参数类型不能写死,而是使用泛型代替。其中泛型OLD代表从数据库查询的集合元素,NEW代表新集合元素,ADDITIONAL稍后介绍。
其次,由于每一种查询任务的处理逻辑都不同,所以需要一个接口来抽象任务的处理TaskProcessor就是做这个工作的。

2.任务处理接口

该接口就是上面提到的TaskProcessor

public interface TaskProcessor<NEW,OLD> {
    NEW handTask(OLD old);
}

其方法入参OLD 表示旧的元素,返回值NEW代表处理后的新元素。

3.额外参数处理

在前面的submitTask方法里有如下代码

   if(additional != null){
       ThreadLocalInfoUtil.setValue("additionalParam", additional);
 	}

为什么需要这块逻辑呢?在调用TaskProcessor类的handTask方法时,如果某个业务处理还需要其他参数,常规做法在handTask方法再加参数,但是这样会影响到所有实现类。
所以,在提交任务时可以传额外的ADDITIONAL参数并放入ThreadLocal,这样在TaskProcessorhandTask方法中,就可以直接从ThreadLocal获取。

使用方式

1.实现TaskProcessor接口

具体业务类会实现TaskProcessor接口。
如下,有三个实现类,分别代表三种业务实现。
在这里插入图片描述
ShowProcessTaskProcessor类为例,如下

@Service("showProcessTaskProcessor")
public class ShowProcessTaskProcessor implements TaskProcessor<OperatorProcessVO, OperatorProcess>{

}

2.注入TaskExecuteFramework

ShowProcessTaskProcessor类中注入

@Autowired
private TaskExecuteFramework taskExecuteFramework;

@Autowired
@Qualifier("showProcessTaskProcessor")
private TaskProcessor<OperatorProcessVO, OperatorProcess> taskProcessor;

然后调用其submitTask方法

 //按10个大小切分数据库集合元素
 List<List<OperatorProcess>> partition = Lists.partition(operatorProcesses, 10);
 List<OperatorProcessVO> vos = new ArrayList<>();
  for (List<OperatorProcess> processes : partition) {
      //提交任务
      vos.addAll(taskExecuteFramework.submitTask(processes, taskProcessor, null));
  }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值