|  | @@ -13,6 +13,7 @@ import com.tzld.piaoquan.ad.engine.commons.param.RankRecommendRequestParam;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.ad.engine.commons.redis.AdRedisHelper;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
 | 
	
		
			
				|  |  | +import com.tzld.piaoquan.ad.engine.commons.thread.ThreadPoolFactory;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.ad.engine.commons.util.DateUtils;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.ad.engine.commons.util.ObjUtil;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.ad.engine.service.entity.*;
 | 
	
	
		
			
				|  | @@ -27,6 +28,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Value;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import java.util.*;
 | 
	
		
			
				|  |  | +import java.util.concurrent.Callable;
 | 
	
		
			
				|  |  | +import java.util.concurrent.ExecutionException;
 | 
	
		
			
				|  |  | +import java.util.concurrent.ExecutorService;
 | 
	
		
			
				|  |  | +import java.util.concurrent.Future;
 | 
	
		
			
				|  |  |  import java.util.function.Function;
 | 
	
		
			
				|  |  |  import java.util.stream.Collectors;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -113,6 +118,9 @@ public abstract class RankStrategyBasic implements RankStrategy {
 | 
	
		
			
				|  |  |      @Value("${filter.config.value:[]}")
 | 
	
		
			
				|  |  |      protected String filterConfigValue;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Value("${feature.branch.config.value:500}")
 | 
	
		
			
				|  |  | +    protected Integer featureBranchConfigValue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private FeatureService featureService;
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
	
		
			
				|  | @@ -153,25 +161,88 @@ public abstract class RankStrategyBasic implements RankStrategy {
 | 
	
		
			
				|  |  |      }};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +//    protected Feature getFeature(ScoreParam param, RankRecommendRequestParam request) {
 | 
	
		
			
				|  |  | +//        List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
 | 
	
		
			
				|  |  | +//        List<String> cidList = adIdList.stream()
 | 
	
		
			
				|  |  | +//                .map(AdPlatformCreativeDTO::getCreativeId)
 | 
	
		
			
				|  |  | +//                .map(Object::toString)
 | 
	
		
			
				|  |  | +//                .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +//        List<String> adVerIdList = adIdList.stream()
 | 
	
		
			
				|  |  | +//                .map(AdPlatformCreativeDTO::getAdVerId)
 | 
	
		
			
				|  |  | +//                .filter(StringUtils::isNotBlank)
 | 
	
		
			
				|  |  | +//                .distinct()
 | 
	
		
			
				|  |  | +//                .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +//        List<Long> skuIdList = adIdList.stream()
 | 
	
		
			
				|  |  | +//                .map(AdPlatformCreativeDTO::getSkuId)
 | 
	
		
			
				|  |  | +//                .filter(Objects::nonNull)
 | 
	
		
			
				|  |  | +//                .distinct()
 | 
	
		
			
				|  |  | +//                .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +//        return featureService.getFeature(cidList, adVerIdList, skuIdList, param);
 | 
	
		
			
				|  |  | +//    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      protected Feature getFeature(ScoreParam param, RankRecommendRequestParam request) {
 | 
	
		
			
				|  |  |          List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
 | 
	
		
			
				|  |  | -        List<String> cidList = adIdList.stream()
 | 
	
		
			
				|  |  | -                .map(AdPlatformCreativeDTO::getCreativeId)
 | 
	
		
			
				|  |  | -                .map(Object::toString)
 | 
	
		
			
				|  |  | -                .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +        Feature finalFeature = null;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        List<String> adVerIdList = adIdList.stream()
 | 
	
		
			
				|  |  | -                .map(AdPlatformCreativeDTO::getAdVerId)
 | 
	
		
			
				|  |  | -                .filter(StringUtils::isNotBlank)
 | 
	
		
			
				|  |  | -                .distinct()
 | 
	
		
			
				|  |  | -                .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +        // 分批处理 AdPlatformCreativeDTO 列表
 | 
	
		
			
				|  |  | +        List<List<AdPlatformCreativeDTO>> adIdBatches = partitionList(adIdList, featureBranchConfigValue);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        List<Long> skuIdList = adIdList.stream()
 | 
	
		
			
				|  |  | -                .map(AdPlatformCreativeDTO::getSkuId)
 | 
	
		
			
				|  |  | -                .filter(Objects::nonNull)
 | 
	
		
			
				|  |  | -                .distinct()
 | 
	
		
			
				|  |  | -                .collect(Collectors.toList());
 | 
	
		
			
				|  |  | -        return featureService.getFeature(cidList, adVerIdList, skuIdList, param);
 | 
	
		
			
				|  |  | +        // 使用 ThreadPoolFactory 获取 DEFAULT 线程池
 | 
	
		
			
				|  |  | +        ExecutorService executorService = ThreadPoolFactory.defaultPool();  // 使用 DEFAULT 线程池
 | 
	
		
			
				|  |  | +        List<Callable<Feature>> tasks = new ArrayList<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for (List<AdPlatformCreativeDTO> batch : adIdBatches) {
 | 
	
		
			
				|  |  | +            // 提取批次中的 cidList、adVerIdList 和 skuIdList
 | 
	
		
			
				|  |  | +            List<String> cidList = batch.stream()
 | 
	
		
			
				|  |  | +                    .map(AdPlatformCreativeDTO::getCreativeId)
 | 
	
		
			
				|  |  | +                    .map(Object::toString)
 | 
	
		
			
				|  |  | +                    .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            List<String> adVerIdList = batch.stream()
 | 
	
		
			
				|  |  | +                    .map(AdPlatformCreativeDTO::getAdVerId)
 | 
	
		
			
				|  |  | +                    .filter(StringUtils::isNotBlank)
 | 
	
		
			
				|  |  | +                    .distinct()
 | 
	
		
			
				|  |  | +                    .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            List<Long> skuIdList = batch.stream()
 | 
	
		
			
				|  |  | +                    .map(AdPlatformCreativeDTO::getSkuId)
 | 
	
		
			
				|  |  | +                    .filter(Objects::nonNull)
 | 
	
		
			
				|  |  | +                    .distinct()
 | 
	
		
			
				|  |  | +                    .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 将每个批次的请求任务封装为 Callable
 | 
	
		
			
				|  |  | +            tasks.add(() -> featureService.getFeature(cidList, adVerIdList, skuIdList, param));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            // 执行所有的任务并等待所有任务完成
 | 
	
		
			
				|  |  | +            List<Future<Feature>> futures = executorService.invokeAll(tasks);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 等待所有任务完成并合并结果
 | 
	
		
			
				|  |  | +            for (Future<Feature> future : futures) {
 | 
	
		
			
				|  |  | +                Feature batchFeature = future.get();  // 获取每个任务的结果
 | 
	
		
			
				|  |  | +                if (finalFeature == null) {
 | 
	
		
			
				|  |  | +                    finalFeature = batchFeature;
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    // 合并特征
 | 
	
		
			
				|  |  | +                    finalFeature.merge(batchFeature);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } catch (InterruptedException | ExecutionException e) {
 | 
	
		
			
				|  |  | +            log.error("getFeature error", e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return finalFeature;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 辅助方法:将列表分成指定大小的批次
 | 
	
		
			
				|  |  | +    private <T> List<List<T>> partitionList(List<T> originalList, Integer batchSize) {
 | 
	
		
			
				|  |  | +        List<List<T>> batches = new ArrayList<>();
 | 
	
		
			
				|  |  | +        for (int i = 0; i < originalList.size(); i += batchSize) {
 | 
	
		
			
				|  |  | +            batches.add(originalList.subList(i, Math.min(i + batchSize, originalList.size())));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return batches;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      protected Set<String> getNoApiAdVerIds() {
 |