基于重量的循环模式

use*_*073 0 java


我正在尝试用Java编写一个简单的算法来选择哪个服务器需要执行一个操作.我想使用一种循环法,但每台服务器上都有一个重量.到目前为止,我编写了以下代码:

public static void main(String[] args) {
    // Weight for each server
    int x = 1;
    int y = 3;

    int counterx = 0;
    int countery = 0;

    for (int ii = 0; ii < 10; ii++) {
        counterx++;
        countery++;
        if (counterx == x) {
            System.out.println("Chosen x ");
            counterx = 0;
        }
        if (countery == y) {
            System.out.println("Chosen y ");
            countery = 0;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,给定两个服务器x和y,我已经存储了权重以分配给x和y变量中的每个服务器以及每个服务器的计数器.这似乎有效,但是如果服务器数量增加,代码将变得非常复杂.是否有任何util包可以帮助我根据权重因子确定要调用的服务器?
谢谢

And*_*own 7

实际上,类型实现NavigableMap是理想的,例如TreeMap.

你需要做一些事情:

  1. 封装您的服务器详细信息(名称,地址,选择权重)
  2. 存储服务器列表(稍后可以添加/删除)
  3. 选择介于0和所有权重之和的随机数.
  4. 在服务器列表中搜索第一台服务器,其中包含此服务器的所有服务器的权重总和大于随机值.

这样,列表中服务器的排序无关紧要.这正是NavigableMap与ceilingEntry方法一起使用的内容.

例如:

public class ServerDetails {
    int weight;
    String address;
    public Server(int weight, String address) { 
        this.weight = weight;
        this.address = address;
    }
    public int getWeight(){return this.weight;}
    public String getAddress(){return this.address;}
}
Run Code Online (Sandbox Code Playgroud)

然后使用以下内容定义服务器池:

public class ServerPool {
    Random someRandGen = new Random();
    TreeMap<Integer, ServerDetails> pool;
    int totalWeight;

    public void init(ArrayList<ServerDetails> servers) {
        this.pool = new TreeMap<Integer, ServerDetails>();
        // create the "weighted selection" list
        totalWeight = 0;
        for(ServerDetails s : servers) {
            //  associate each server with the sum of the weights so far
            totalWeight += s.getWeight();
            this.pool.put(totalWeight, s);
        }
    }

    public ServerDetails getNext() {
        int rnd = someRandGen.nextInt(this.totalWeight);
        return pool.ceilingEntry(rnd).getValue();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以相应地为池定义添加/删除方法.与以下示例代码一起使用,每个选择的次数百分比为:

a: 11.1%
b: 40.8%
c: 19.6%
d: 28.5%

码:

ArrayList<ServerDetails> servers = new ArrayList<ServerDetails>(){{
    add(new ServerDetails(10, "a"));
    add(new ServerDetails(40, "b"));
    add(new ServerDetails(20, "c"));
    add(new ServerDetails(30, "d"));
}}; 

ServerPool serverPool = new ServerPool();
serverPool.init(servers);
for (int i = 0; i < 10000; i++)
    System.out.println(serverPool.getNext().getAddress());
Run Code Online (Sandbox Code Playgroud)