2010-01-11 45 views
10

Tôi có một danh sách các máy chủ trong một mảng mà represnt các máy chủ có sẵn để làm một công việc cụ thể. Hiện tại tôi chỉ đơn giản là lặp qua danh sách tìm kiếm và thiết lập comm với một máy chủ để kiểm tra nó không bận rộn. Nếu không, tôi sẽ gửi một công việc cho nó. Cách tiếp cận này có xu hướng có nghĩa là máy chủ đầu tiên trong danh sách có xu hướng nóng lên một cách kín đáo với tải không cân bằng đúng với các máy chủ còn lại.vòng lặp lập lịch trình vòng lặp java

trong giả ..

for (Host h : hosts) { 

    //checkstatus 
    if status == job accepted break; 

} 

Tôi muốn cân bằng tải này đúng giữa các host tức là lần đầu tiên máy chủ được sử dụng một thời gian 2 phương pháp này được sử dụng chủ 2. Chỉ cần tự hỏi rằng giải pháp thanh lịch nhất đây là ??

Cảm ơn W

+0

Tôi nghĩ có lẽ im sau là . Có thể triển khai một trình vòng lặp tùy chỉnh cho danh sách các máy chủ của tôi. Chỉ cần không chắc chắn làm thế nào để làm điều này. Tôi có một cảm giác tôi cần phải mở rộng lớp ArrayList và thực hiện lớp ListIterator âm thanh này hợp lý không? – wmitchell

Trả lời

11

Bạn có thể tạo ra một loại mới của Iterable cung cấp round-robin lặp:

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(); 
      } 

     }; 
    } 
} 

Bạn cần phải xác định máy của bạn như RoundRobin<Host>.

[FIXED dựa trên nhận xét của Mirko]

+2

Giải pháp tốt. Một vấn đề nhỏ mặc dù: Thực hiện coll.get (index) là tốn kém cho một số danh sách. Tôi muốn nói duy trì một iterator và làm tiếp theo trên nó, và nhận được một iterator tươi khi bạn chạy ra khỏi các yếu tố là tốt hơn. – Buhb

+0

Đây là loại điều im sau khi cảm ơn Itay và Buhb – wmitchell

+0

Việc triển khai của bạn là lỗi, bởi vì lệnh gọi đầu tiên của next() cung cấp một giá trị rỗng! Xem: http://stackoverflow.com/a/12931655/1268954 – Mirko

4

Nếu danh sách là có thể thay đổi và chi phí chỉnh sửa nó là không đáng kể so với I/O với các host, bạn chỉ có thể xoay nó:

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

Nếu bạn đang tạo Iterator, tốt nhất là tạo bản sao phòng thủ trước và yêu cầu trình vòng lặp hoạt động trên đó.

return new MyIterator(ImmutableList.<T>copyOf(list)); 
+1

'of' phải là 'copyOf'; nếu không bạn có một danh sách chứa thành phần duy nhất của nó là một tham chiếu đến danh sách gốc. –

+0

Có. Xin lỗi, đúng hơn là một lỗi đánh máy sai – gpampara

4

IMHO Java API chuẩn đã cung cấp cách dễ dàng để thực hiện việc này mà không cần phải thực hiện Iterator tùy chỉnh. Đơn giản chỉ cần sử dụng một Deque nơi bạn muốn kéo máy chủ đầu tiên, sử dụng hoặc loại bỏ nó, sau đó gắn nó trở lại vào cuối của Deque. Dưới đây là một số mã mẫu:

// 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...  
} 

Đây chỉ là mẫu mà bạn luôn ping các đơn đặt hàng vòng tròn trong vòng lặp chỉ kết thúc khi một trong số đó có sẵn và thực hiện công việc. Bạn có thể tinker với nó một cách dễ dàng để đi chỉ quanh hàng đợi một lần (sử dụng một bộ đếm với một bộ tối đa kích thước của hàng đợi) hoặc một số lần beofre ném một ngoại lệ, hoặc ngủ giữa các vòng để tránh đập máy khi tất cả đang bận rộn .

1

thực hiện RoundRobin Mỹ, dựa trên việc thực hiện 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"); 
      } 
     }; 
    } 
} 

Và Junit TestCase

/** 
* 
* @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); 
     } 
    } 
} 
0
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; 
     } 
    } 

đâu Filter là

public interface Filter<T> { 

     public boolean accept(T t); 

    } 
Các vấn đề liên quan