按权重分配任务
public class TaskAlloc { private Map<String, Integer> weight; public Map<String, Integer> getWeight() { return weight; } public Map<String, Integer> getCmpltedTask() { return cmpltedTask; } public AtomicInteger getAllcodCount() { return allcodCount; } private Map<String, Integer> cmpltedTask = new ConcurrentHashMap<String, Integer>(); private AtomicInteger allcodCount = new AtomicInteger(0); public TaskAlloc(Map<String, Integer> weight) throws Exception { this.weight = weight; Integer sum = MapHelper.reduce(weight, 0, (init, current) -> init + current); if (sum != 100) { throw new Exception("权重之合必须为100"); } for (String key : weight.keySet()) { cmpltedTask.put(key, 0); } } public String alloc() { int ac = allcodCount.getAndIncrement(); String key = getMin(cmpltedTask, weight, ac); cmpltedTask.put(key, cmpltedTask.get(key) + 1); return key; } private static String getMin(Map<String, Integer> allocedRecordMap, Map<String, Integer> weightMap, Integer allocedCount) { double min = 1; String result = null; for (Map.Entry<String, Integer> entry : weightMap.entrySet()) { String key = entry.getKey(); //计算权重所占最大的比例 double maxRatio = entry.getValue() * 1.0 / 100; //计算已分配的比例 double cmpltedRatio = allocedCount == 0 ? 0 : allocedRecordMap.get(key) * 1.0 / allocedCount; double ratio = cmpltedRatio / maxRatio; if (ratio < min) { result = key; min = ratio; } } return result; } }
第2种算法
public class TaskAlloc { /** * 任务权重Map,Key为任务标识,Value为任务对应的权重 */ private Map<String, Integer> weight; public Map<String, Integer> getWeight() { return weight; } /** * ctor * @param weight 任务权重Map,Key为任务标识,Value为任务对应的权重 * @throws Exception */ public TaskAlloc(Map<String, Integer> weight) throws Exception { this.weight = weight; Integer sum = MapHelper.reduce(weight, 0, (result, current) -> result + current); if (sum != 100) { throw new Exception("权重之合必须为100"); } } /** * 分配任务实现. * @param taskAllocStatisticsMapFunc 提供所有任务的分配统计Map Key为任务标识,Value为该任务已分配总数 * @return 需要分配的任务标识 * @throws Exception 任务的分配统计Map不能为空 */ public String alloc(Supplier<Map<String, Integer>> taskAllocStatisticsMapFunc)throws Exception { Map<String, Integer> taskAllocStatisticsMap = taskAllocStatisticsMapFunc.get(); if (taskAllocStatisticsMap == null) { throw new Exception("任务的分配统计Map不能为空"); } int allocedCount = MapHelper.reduce(taskAllocStatisticsMap, 0, (result, currentValue) -> result + currentValue); String key = getMin(taskAllocStatisticsMap, weight, allocedCount); taskAllocStatisticsMap.put(key, taskAllocStatisticsMap.get(key) + 1); return key; } /** * 找到分配比率最小的任务标识(即需要分配的任务标识) * @param taskAllocStatisticsMap 任务的分配统计Map(Key为任务标识,Value为该任务已分配总数) * @param weightMap 任务的权重Map * @param allocedCount 已分配的总次数 * @return 需要分配的任务标识 */ private static String getMin(Map<String, Integer> taskAllocStatisticsMap, Map<String, Integer> weightMap, Integer allocedCount) { double min = 1; String result = null; for (Map.Entry<String, Integer> entry : weightMap.entrySet()) { String key = entry.getKey(); //计算权重所占最大的比例 double maxRatio = entry.getValue() * 1.0 / 100; //计算已分配的比例 double cmpltedRatio = allocedCount == 0 ? 0 : taskAllocStatisticsMap.getOrDefault(key, 0) * 1.0 / allocedCount; double ratio = cmpltedRatio / maxRatio; if (ratio < min) { result = key; min = ratio; } } return result; } }