定义接口public interface RoundRobin {
T nextData();
}
实现
算法来自nginxpublic class WeightedRoundRobin implements RoundRobin {
private List> items = new ArrayList<>();
public WeightedRoundRobin(Map datas) {
List> initItems = datas.entrySet()
.stream()
.map(e -> new Item<>(e.getKey(), e.getValue()))
.collect(Collectors.toList());
items.addAll(initItems);
}
public T nextData() {
Item bestItem = null;
int total = 0;
for (Item 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> getItems() {
return items;
}
public void setItems(List> items) {
this.items = items;
}
public static final class Item {
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 testDatas = new HashMap() {{
put(1, 3); // 权重3
put(2, 5); // 权重5
put(3, 8); // 权重8
}};
WeightedRoundRobin roundRobin = new WeightedRoundRobin<>(testDatas);
for (int i = 0; i < 20; i++) {
LOGGER.info("id: {}", roundRobin.nextData());
}