定义接口
public interface RoundRobin<T> { T nextData(); }
实现
算法来自Nginx
public class WeightedRoundRobin<T> implements RoundRobin<T> { private List<Item<T>> items = new ArrayList<>(); public WeightedRoundRobin(Map<T, Integer> datas) { List<Item<T>> initItems = datas.entrySet() .stream() .map(e -> new Item<>(e.getKey(), e.getValue())) .collect(Collectors.toList()); items.addAll(initItems); } public T nextData() { Item<T> bestItem = null; int total = 0; for (Item<T> currentItem : items) { currentItem.currentWeight += currentItem.effectiveWeight; total += currentItem.effectiveWeight; if (currentItem.effectiveWeight < currentItem.weight) { currentItem.effectiveWeight++; } if (bestItem == null || currentItem.currentWeight > bestItem.currentWeight) { bestItem = currentItem; } } if (bestItem == null) { return null; } bestItem.currentWeight -= total; return bestItem.getData(); } public List<Item<T>> getItems() { return items; } public void setItems(List<Item<T>> items) { this.items = items; } public static final class Item<T> { private T data; private int weight; private int effectiveWeight; private int currentWeight; public Item(T data, int weight) { this.data = data; this.weight = weight; } public T getData() { return data; } public void setData(T data) { this.data = data; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getEffectiveWeight() { return effectiveWeight; } public void setEffectiveWeight(int effectiveWeight) { this.effectiveWeight = effectiveWeight; } public int getCurrentWeight() { return currentWeight; } public void setCurrentWeight(int currentWeight) { this.currentWeight = currentWeight; } @Override public String toString() { return "Item{" + "data=" + data + ", weight=" + weight + ", effectiveWeight=" + effectiveWeight + ", currentWeight=" + currentWeight + '}'; } } }
使用
Map<Integer, Integer> testDatas = new HashMap<Integer, Integer>() {{ put(1, 3); // 权重3 put(2, 5); // 权重5 put(3, 8); // 权重8 }}; WeightedRoundRobin<Integer> roundRobin = new WeightedRoundRobin<>(testDatas); for (int i = 0; i < 20; i++) { LOGGER.info("id: {}", roundRobin.nextData()); }