循环调度java迭代器

循环调度java迭代器,java,scheduling,iterator,Java,Scheduling,Iterator,我在一个数组中有一个主机列表,它表示可用于执行特定任务的服务器。目前,我只是在列表中重复查找,并与主机建立通信,以检查其是否繁忙。如果没有,我会给它发一份工作。这种方法往往意味着列表中的第一台主机往往会持续变热,而负载与其余可用主机之间的平衡不正确 在伪代码中 for (Host h : hosts) { //checkstatus if status == job accepted break; } 我希望在主机之间正确平衡此负载,即第一次使用主机1,第二次使用主机2。只

我在一个数组中有一个主机列表,它表示可用于执行特定任务的服务器。目前,我只是在列表中重复查找,并与主机建立通信,以检查其是否繁忙。如果没有,我会给它发一份工作。这种方法往往意味着列表中的第一台主机往往会持续变热,而负载与其余可用主机之间的平衡不正确

在伪代码中

for (Host h : hosts) {

    //checkstatus
    if status == job accepted break;

}
我希望在主机之间正确平衡此负载,即第一次使用主机1,第二次使用主机2。只是想知道最优雅的解决方案是

谢谢
W

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

公共类循环实现了Iterable{
私人名单;
公共循环(列表coll){this.coll=coll;}
公共迭代器迭代器(){
返回新的迭代器(){
私有整数指数=0;
@凌驾
公共布尔hasNext(){
返回true;
}
@凌驾
公共交通工具{
T res=coll.get(索引);
索引=(索引+1)%coll.size();
返回res;
}
@凌驾
公共空间删除(){
抛出新的UnsupportedOperationException();
}
};
}
}
您需要将主机定义为
RoundRobin


[根据Mirko的评论修复]

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

List<String> list = Arrays.asList("one", "two", "three");
Collections.rotate(list, -1);
System.out.println(list);
List List=Arrays.asList(“一”、“二”、“三”);
集合。轮换(列表,-1);
系统输出打印项次(列表);

有一个实用方法可以实现您想要的功能。

如果您要创建迭代器,最好先创建一个防御副本,并让迭代器处理该副本

return new MyIterator(ImmutableList.<T>copyOf(list));
返回新的MyIterator(ImmutableList.copyOf(list));

IMHO标准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...    
}
//初始化数据块。这可能在您的类构造函数中。
Deque dq=新的ArrayDeque();
addAll(Arrays.asList(hosts));
void sendJob(Job myJob){
布尔jobInProcess=false;
做{
Host Host=dq.removeFirst();//从顶部删除主机
如果(!host.isBusy()){
host.sendJob(myJob);
jobInProcess=true;
}
dq.addLast(主机);//将主机放回末尾
} 
而(!jobInProcess);//可能会添加另一个条件以防止无限循环。。。
}

这只是一个示例,您总是在循环中按循环顺序ping主机,循环仅在其中一个可用并接受作业时结束。您可以轻松地修改它,只在队列中循环一次(使用一个最大值设置为队列大小的计数器),或者多次重复抛出异常,或者在两次循环之间睡觉,以避免在所有主机都忙时碰撞主机

My RoundRobin实现,基于

/**
* 
*@作者米尔科·舒尔茨
*
*@param
*/
公共类循环实现了Iterable{
私人最终名单;
公开循环赛(最终名单){
this.coll=NullCheck.ThroweExceptionIfNull(coll,“集合为null”);
}
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
私有整数索引;
@凌驾
公共布尔hasNext(){
返回true;
}
@凌驾
公共交通工具{
this.index=this.index%RoundRobin.this.coll.size();
final T=RoundRobin.this.coll.get(this.index);
这个.index++;
返回t;
}
@凌驾
公共空间删除(){
抛出新的IllegalArgumentException(“删除不允许”);
}
};
}
}
还有Junit测试用例

/**
 * 
 * @author Mirko Schulze
 *
 */
@RunWith(JUnit4.class)
public class RoundRobinTest extends TestCase {

    private List<Integer> getCollection() {
        final List<Integer> retval = new Vector<Integer>();
        retval.add(Integer.valueOf(1));
        retval.add(Integer.valueOf(2));
        retval.add(Integer.valueOf(3));
        retval.add(Integer.valueOf(4));
        retval.add(Integer.valueOf(5));
        return retval;
    }

    @Test
    public void testIteration() {
        final List<Integer> l = this.getCollection();
        final Integer frst = l.get(0);
        final Integer scnd = l.get(1);
        final Integer thrd = l.get(2);
        final Integer frth = l.get(3);
        final Integer last = l.get(4);
        Assert.assertEquals("die Collection hat für diesen Test nicht die passende Größe!", 5, l.size());
        final RoundRobin<Integer> rr = new RoundRobin<Integer>(l);
        final Iterator<Integer> i = rr.iterator();
        for (int collectionIterations = 0; collectionIterations < 4; collectionIterations++) {
            final Integer i1 = i.next();
            Assert.assertEquals("nicht das erste Element", frst, i1);
            final Integer i2 = i.next();
            Assert.assertEquals("nicht das zweite Element", scnd, i2);
            final Integer i3 = i.next();
            Assert.assertEquals("nicht das dritte Element", thrd, i3);
            final Integer i4 = i.next();
            Assert.assertEquals("nicht das vierte Element", frth, i4);
            final Integer i5 = i.next();
            Assert.assertEquals("nicht das letzte Element", last, i5);
        }
    }
}
/**
* 
*@作者米尔科·舒尔茨
*
*/
@RunWith(JUnit4.class)
公共类RoundRobinTest扩展了TestCase{
私有列表getCollection(){
最终列表retval=新向量();
retval.add(Integer.valueOf(1));
retval.add(Integer.valueOf(2));
retval.add(Integer.valueOf(3));
retval.add(Integer.valueOf(4));
retval.add(Integer.valueOf(5));
返回返回;
}
@试验
公开无效证明(){
最终列表l=this.getCollection();
最终整数frst=l.get(0);
最终整数scnd=l.get(1);
最终整数thrd=l.get(2);
最终整数frth=l.get(3);
最终整数last=l.get(4);
Assert.assertEquals(“模具收集hat für diesen Test nicht die passende Grße!”,5,l.size());
最终循环rr=新循环(l);
最终迭代器i=rr.Iterator();
对于(int collectionIterations=0;collectionIterations<4;collectionIterations++){
最终整数i1=i.next();
Assert.assertEquals(“nicht das erste元素”,第一,i1);
最终整数i2=i.next();
Assert.assertEquals(“nicht das zweite元素”,scnd,i2);
最终整数i3=i.next();
Assert.assertEquals(“不含滴水元素”,第三条第三款);
最终整数i4=i.next();
Assert.assertEquals(“nicht das vierte元素”,第1页,第4页);
最终整数i5=i.next();
Assert.assertEquals(“nicht das letzte元素”,最后,i5);
}
}
}
公共类RoundRobinitor实现可序列化{
私有静态最终长serialVersionUID=-2472030608
/**
 * 
 * @author Mirko Schulze
 *
 */
@RunWith(JUnit4.class)
public class RoundRobinTest extends TestCase {

    private List<Integer> getCollection() {
        final List<Integer> retval = new Vector<Integer>();
        retval.add(Integer.valueOf(1));
        retval.add(Integer.valueOf(2));
        retval.add(Integer.valueOf(3));
        retval.add(Integer.valueOf(4));
        retval.add(Integer.valueOf(5));
        return retval;
    }

    @Test
    public void testIteration() {
        final List<Integer> l = this.getCollection();
        final Integer frst = l.get(0);
        final Integer scnd = l.get(1);
        final Integer thrd = l.get(2);
        final Integer frth = l.get(3);
        final Integer last = l.get(4);
        Assert.assertEquals("die Collection hat für diesen Test nicht die passende Größe!", 5, l.size());
        final RoundRobin<Integer> rr = new RoundRobin<Integer>(l);
        final Iterator<Integer> i = rr.iterator();
        for (int collectionIterations = 0; collectionIterations < 4; collectionIterations++) {
            final Integer i1 = i.next();
            Assert.assertEquals("nicht das erste Element", frst, i1);
            final Integer i2 = i.next();
            Assert.assertEquals("nicht das zweite Element", scnd, i2);
            final Integer i3 = i.next();
            Assert.assertEquals("nicht das dritte Element", thrd, i3);
            final Integer i4 = i.next();
            Assert.assertEquals("nicht das vierte Element", frth, i4);
            final Integer i5 = i.next();
            Assert.assertEquals("nicht das letzte Element", last, i5);
        }
    }
}
    public class RoundRobinIterator<T> implements Serializable {

        private static final long serialVersionUID = -2472203060894189676L;
        //
        private List<T> list;
        private Iterator<T> it;
        private AtomicInteger index = new AtomicInteger(0);

        public RoundRobinIterator(List<T> list) throws NullPointerException {
            super();
            if (list==null) {
                throw new NullPointerException("List is null");
            }
            this.list=Collections.unmodifiableList(list);
        }
        public RoundRobinIterator(Collection<T> values) {
            this(new ArrayList<T>(values));
        }
        public RoundRobinIterator(Iterator<T> values) {
            this(copyIterator(values));
        }
        public RoundRobinIterator(Enumeration<T> values) {
            this(Collections.list(values));
        }



        private final List<T> getList() {
            return list;
        }
        private final Iterator<T> getIt() {
            return it;
        }
        public final int size() {
            return list.size();
        }
        public final synchronized T getNext(Filter<T> filter) {
            int start = index.get();
            T t = getNext();
            T result = null;
            while ((result==null) && (start!=getIndex())) {
                if (filter.accept(t)) {
                    result=t;
                } else {
                    t = getNext();
                }
            }
            return result;
        }

        public final synchronized T getNext() {
            if (getIt()==null) {
                if (getList().size()==0) {
                    index.set(0);
                    return null;
                } else {
                    it = getList().iterator();
                    index.set(0);
                    return it.next();
                }
            } else if (it.hasNext()) {
                index.incrementAndGet();
                return it.next();
            } else {
                if (list.size()==0) {
                    index.set(0);
                    return null;
                } else {
                    index.set(0);
                    it = list.iterator();               
                    return it.next();
                }
            } 
        }

        public final synchronized int getIndex() {
            return index.get();
        }


        private static <T> List<T> copyIterator(Iterator<T> iter) {
            List<T> copy = new ArrayList<T>();
            while (iter.hasNext()) {
                copy.add(iter.next());
            }
            return copy;
        }
    }
    public interface Filter<T> {

        public boolean accept(T t);

    }