wmi*_*ell 13 java iterator scheduling
我在一个数组中有一个主机列表,它们代表可用于执行特定工作的服务器.目前我只是通过列表迭代查找并与主机建立通信以检查其不忙.如果没有,我会发一份工作.这种方法往往意味着列表中的第一个主机容易变得热,并且负载与其他可用主机不能正确平衡.
在伪代码..
for (Host h : hosts) {
//checkstatus
if status == job accepted break;
}
Run Code Online (Sandbox Code Playgroud)
我想在主机之间正确平衡这个负载,即第一次使用主机,第二次使用方法主机2.只是想知道最优雅的解决方案是?
谢谢你
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的评论修复]
如果列表是可变的,并且与主机的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引发异常,或者在两回合之间睡觉以避免在所有忙碌时撞主机。
| 归档时间: |
|
| 查看次数: |
21192 次 |
| 最近记录: |