wangyunpeng 1 день назад
Родитель
Сommit
bf2df8d5ef

+ 20 - 13
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java

@@ -804,38 +804,45 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
     }
 
     /**
-     * 通用 N 池轮转穿插(确定性,无随机):
-     * - 池按传入顺序轮转,每池取 1 条,跳过已耗尽的池继续下一轮
+     * 通用 N 池轮转穿插:
+     * - 池列表随机打乱后,按新顺序轮转,每池取 1 条,跳过已耗尽的池继续下一轮
      * - 跨池 video_id / 标题去重;某池耗尽后自动从轮转中移除
      */
     private List<VideoContentItemVO> interleaveMultiPools(List<List<VideoContentItemVO>> pools) {
         int n = pools.size();
+        // 随机打乱池顺序,轮转遍历
+        List<Integer> order = new ArrayList<>(n);
+        for (int i = 0; i < n; i++) order.add(i);
+        Collections.shuffle(order);
+
         int[] pointers = new int[n];
         boolean[] exhausted = new boolean[n];
         for (int i = 0; i < n; i++) {
-            if (pools.get(i) == null || pools.get(i).isEmpty()) exhausted[i] = true;
+            List<VideoContentItemVO> p = pools.get(order.get(i));
+            if (p == null || p.isEmpty()) exhausted[order.get(i)] = true;
         }
         Set<Long> seenIds = new HashSet<>();
         Set<String> seenTitles = new HashSet<>();
         List<VideoContentItemVO> out = new ArrayList<>();
 
-        int cur = 0;
+        int pos = 0;
         while (true) {
             // 跳过已耗尽的池
-            int started = cur;
-            while (exhausted[cur]) {
-                cur = (cur + 1) % n;
-                if (cur == started) return out; // 全部耗尽
+            int started = pos;
+            while (exhausted[order.get(pos)]) {
+                pos = (pos + 1) % n;
+                if (pos == started) return out; // 全部耗尽
             }
 
-            List<VideoContentItemVO> pool = pools.get(cur);
-            while (pointers[cur] < pool.size()) {
-                VideoContentItemVO v = pool.get(pointers[cur]++);
+            int idx = order.get(pos);
+            List<VideoContentItemVO> pool = pools.get(idx);
+            while (pointers[idx] < pool.size()) {
+                VideoContentItemVO v = pool.get(pointers[idx]++);
                 if (tryEmit(v, seenIds, seenTitles, out)) break;
             }
-            if (pointers[cur] >= pool.size()) exhausted[cur] = true;
+            if (pointers[idx] >= pool.size()) exhausted[idx] = true;
 
-            cur = (cur + 1) % n;
+            pos = (pos + 1) % n;
         }
     }