循环调度java迭代器

wmi*_*ell 13 java iterator scheduling

我在一个数组中有一个主机列表,它们代表可用于执行特定工作的服务器.目前我只是通过列表迭代查找并与主机建立通信以检查其不忙.如果没有,我会发一份工作.这种方法往往意味着列表中的第一个主机容易变得热,并且负载与其他可用主机不能正确平衡.

在伪代码..

for (Host h : hosts) {

    //checkstatus
    if status == job accepted break;

}
Run Code Online (Sandbox Code Playgroud)

我想在主机之间正确平衡这个负载,即第一次使用主机,第二次使用方法主机2.只是想知道最优雅的解决方案是?

谢谢你

Buh*_*uhb 20

Google集合有一个实用程序Iterators.cycle(Iterable<T> iterable),可以执行您想要的操作.


Ita*_*man 16

您可以创建一种新的Iterable,它提供循环迭代:

public class RoundRobin<T> implements Iterable<T> {
      private List<T> coll;

      public RoundRobin(List<T> coll) { this.coll = coll; }

      public Iterator<T> iterator() { 
         return new Iterator<T>() {
            private int index = 0;

            @Override
            public boolean hasNext() {
                return true;
            }

            @Override
            public T next() {
                T res = coll.get(index);
                index = (index + 1) % coll.size();
                return res;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }

        };
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要将主机定义为RoundRobin<Host>.

[根据Mirko的评论修复]

  • 好的解决方案 但是一个小问题:对某些列表执行coll.get(index)是很昂贵的.我会说维护一个迭代器并在其上做下一步,并且当你耗尽元素时获得一个新的迭代器更好. (2认同)

McD*_*ell 7

如果列表是可变的,并且与主机的I/O相比,编辑它的成本可以忽略不计,您可以只旋转它:

List<String> list = Arrays.asList("one", "two", "three");
Collections.rotate(list, -1);
System.out.println(list);
Run Code Online (Sandbox Code Playgroud)


小智 5

恕我直言,标准的Java API已经提供了一种简便的方法来完成此任务,而无需诉诸外部库,甚至无需实现自定义迭代器。只需在您要拉出第一个服务器的地方使用Deque,使用或丢弃它,然后将其附加回Deque的末尾即可。这是一些示例代码:

// Initialize the Deque. This might be at your class constructor. 
Deque<Host> dq = new ArrayDeque<Host>();
dq.addAll(Arrays.asList(hosts)); 

void sendJob(Job myJob) {
    boolean jobInProcess = false;
    do {
        Host host = dq.removeFirst(); // Remove the host from the top
        if(!host.isBusy()) {
            host.sendJob(myJob);
            jobInProcess = true;
        }
        dq.addLast(host); // Put the host back at the end
    } 
    while(!jobInProcess); // Might add another condition to prevent an infinite loop...    
}
Run Code Online (Sandbox Code Playgroud)

这只是一个示例,在此示例中,您始终以循环方式对主机进行ping操作,直到只有其中一个主机可用并接管工作时该主机才会结束。您可以轻而易举地修改它,使其仅绕过队列一次(使用最大设置为队列大小的计数器)或多次beofre引发异常,或者在两回合之间睡觉以避免在所有忙碌时撞主机。