代码之家  ›  专栏  ›  技术社区  ›  wmitchell

循环调度java迭代器

  •  11
  • wmitchell  · 技术社区  · 16 年前

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

    在伪代码中。。

    for (Host h : hosts) {
    
        //checkstatus
        if status == job accepted break;
    
    }
    

    我想在主机之间适当平衡此负载,即第一次使用主机1第二次使用此方法主机2。只是想知道最优雅的解决方案是??

    谢谢

    7 回复  |  直到 16 年前
        1
  •  20
  •   Rao CrashOverload    9 年前

    您可以创建一种新的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();
                }
    
            };
        }
    }
    

    RoundRobin<Host> .

    [根据米尔科的评论修正]

        2
  •  21
  •   Buhb    16 年前

    Google collections 有一个实用的方法 Iterators.cycle(Iterable<T> iterable) 那正是你想要的。

        3
  •  8
  •   McDowell rahul gupta    16 年前

    List<String> list = Arrays.asList("one", "two", "three");
    Collections.rotate(list, -1);
    System.out.println(list);
    
        4
  •  6
  •   Jordi Hernández    15 年前

    IMHO标准JavaAPI已经提供了一种简单的方法来实现这一点,无需借助外部库,甚至无需实现自定义迭代器。只需使用一个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...    
    }
    

        5
  •  0
  •   Community Mohan Dere    9 年前

    我的循环执行,基于 https://stackoverflow.com/a/2041772/1268954

    /**
     * 
     * @author Mirko Schulze
     *
     * @param <T>
     */
    public class RoundRobin<T> implements Iterable<T> {
    
        private final List<T>   coll;
    
        public RoundRobin(final List<T> coll) {
            this.coll = NullCheck.throwExceptionIfNull(coll, "collection is null");
        }
    
        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
    
                private int index;
    
                @Override
                public boolean hasNext() {
                    return true;
                }
    
                @Override
                public T next() {
                    this.index = this.index % RoundRobin.this.coll.size();
                    final T t = RoundRobin.this.coll.get(this.index);
                    this.index++;
                    return t;
                }
    
                @Override
                public void remove() {
                    throw new IllegalArgumentException("remove not allowd");
                }
            };
        }
    }
    

    还有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);
            }
        }
    }
    
        6
  •  0
  •   Vigilant Vedant    6 年前

    提供的实现有缺陷,在并行性的情况下可能会失败,我这样做的最简单方法是使用循环链表,其指针由原子整数维护。

        7
  •  -1
  •   gvlasov    11 年前

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

    return new MyIterator(ImmutableList.<T>copyOf(list));
    
        8
  •  -1
  •   FrederikH    10 年前
        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);
    
        }