3

有一个名为 LinkedList 的名称busyList跟踪所有忙碌的机器。一台机器可能忙碌或可用id。当机器空闲时,它会从列表中删除。

以下是机器空闲/忙碌时触发的方法

@Override
public void cloudSimEventFired(CloudSimEvent e) {
    if(e.getId() == CloudSimEvents.EVENT_CLOUDLET_ALLOCATED_TO_VM) {
        int vmId = (Integer) e.getParameter(Constants.PARAM_VM_ID);
        busyList.add(vmId);
    }else if(e.getId() == CloudSimEvents.EVENT_VM_FINISHED_CLOUDLET) {
        int vmId = (Integer) e.getParameter(Constants.PARAM_VM_ID);
        busyList.remove(new Integer(vmId));
    }
}

一个名为allMap(用于分配映射)的映射以机器的 id 作为其键和一个对象class VmAllocation作为其值。的属性VmAllocation是:

maxAlloc (which tells the maximum times a machine can be returned)
currAlloc (which tells the current count)

/*
   allMap.put(id, new VmAllocation(o.getMemory()/512, 0));

   o.getMemory()/512 => maxAlloc
   0 => currAlloc

   This map has been initialized earlier.Like for 3 machines id will be 0,1,2
   As the machine will be returned currAlloc will be incremented by 1
   but it cannot exceed maxAlloc.  
*/

我必须以循环方式返回机器,同时保持视野,我不会返回此刻正忙的机器。busyList.contains(id)如果返回 true,则表示机器很忙,下一个可用的机器(在 allMap 中)返回还考虑到它不会得到比maxAlloc为它设置的更多。例如,如果1来忙,则如果不忙且未超过,2则将返回2currAllocmaxAlloc

以下是必须返回机器并从封闭类外部多次调用的方法。

@Override
    public int getNextAvailableVm() {
                  // return the id
    }   

这是算法的一般工作方式:

Let the id of the machines inside the allMap be :
     0,1,2,3,4
     0 has maxAlloc of 4
     1 has maxAlloc of 4
     2,3 has maxAlloc of 2
     4 has maxAlloc of 1

    The ideal order of returning will be :
    0000 1111 22 33 4 0000 1111 22 33 4 00....

但这只有在没有一台机器忙碌时才会发生。但是如果机器很忙,订单可能是这样的:

0 0 1 2 0 1 0 1 ....

请注意,机器返回的次数不能超过maxAlloc,如果发现机器繁忙,下一台将被返回的机器可能就在当前繁忙的机器旁边,并且它本身不忙(也 currAlloc 应该不超过 maxAlloc)

如果 maxAlloc = 5,则 currAlloc 限制为 4。因为它的计数从 0 开始

我无法实现这个逻辑。帮我做这件事。

4

2 回答 2

1

我对你的问题很感兴趣,所以我想出了这个解决方案,它可能对你有用。该代码中没有健全性检查,它只是一个概念证明。

事件:

public class CloudSimEvent {

    private final int id;
    private final boolean allocated;

    public CloudSimEvent(int id, boolean allocated) {
        super();
        this.id = id;
        this.allocated = allocated;
    }

    public int getID() {
        return id;
    }

    public boolean allocated() {
        return allocated;
    }

    public boolean finished() {
        return !allocated;
    }

}

事件界面

public interface CloudSimEventListener {

    public void cloudSimEventFired(CloudSimEvent e);

}

VMAllocation 对象

public final class VMAllocation implements Comparable<VMAllocation> {

    private final int id;
    private final int maxAlloc;
    private final int currAlloc;

    public VMAllocation(int id, int maxAlloc, int currAlloc) {
        super();
        this.id = id;
        this.maxAlloc = maxAlloc;
        this.currAlloc = currAlloc;
    }

    public VMAllocation allocate() {
        return new VMAllocation(id, maxAlloc, currAlloc + 1);
    }

    public VMAllocation finish() {
        return new VMAllocation(id, maxAlloc, currAlloc - 1);
    }

    public boolean isBusy() {
        return currAlloc >= maxAlloc;
    }

    public int getId() {
        return id;
    }

    @Override
    public int compareTo(VMAllocation o) {
        if (isBusy() && !o.isBusy()) {
            return 1;
        } else if (!isBusy() && o.isBusy()) {
            return -1;
        } else {
            return Integer.compare(id, o.id);
        }
    }

    @Override
    public String toString() {
        return "id: " + id + " currAlloc: " + currAlloc + " maxAlloc: "
                + maxAlloc + " is-busy: " + isBusy();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + currAlloc;
        result = prime * result + id;
        result = prime * result + maxAlloc;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        VMAllocation other = (VMAllocation) obj;
        if (currAlloc != other.currAlloc)
            return false;
        if (id != other.id)
            return false;
        if (maxAlloc != other.maxAlloc)
            return false;
        return true;
    }

}

RRS调度器

import java.util.Arrays;
import java.util.Iterator;
import java.util.PriorityQueue;

public class RRSheduler implements CloudSimEventListener {

    private final PriorityQueue<VMAllocation> queue = new PriorityQueue<>();

    public void addVMAllocation(VMAllocation allocation) {
        synchronized (queue) {
            queue.add(allocation);
        }
    }

    @Override
    public void cloudSimEventFired(CloudSimEvent e) {
        VMChanged(e.getID(), e.allocated());
    }

    private void VMChanged(int id, boolean allocation) {
        synchronized (queue) {
            Iterator<VMAllocation> it = queue.iterator();
            VMAllocation newAllocation = null;
            while (it.hasNext()) {
                VMAllocation vmAllocation = it.next();
                if (vmAllocation.getId() == id) {
                    if (allocation)
                        newAllocation = vmAllocation.allocate();
                    else
                        newAllocation = vmAllocation.finish();
                    it.remove();
                    break;
                }
            }

            if (newAllocation != null)
                queue.add(newAllocation);
        }
    }

    public VMAllocation getNextFreeVMAllocation() {
        synchronized (queue) {
            VMAllocation allocation = queue.element();
            return allocation.isBusy() ? null : allocation;
        }
    }

    @Override
    public String toString() {
        synchronized (queue) {
            VMAllocation[] arr = queue.toArray(new VMAllocation[] {});
            Arrays.sort(arr);
            return Arrays.toString(arr);
        }
    }
}

简单的测试程序

public class TestRR {

    public static void main(String[] args) {
        RRSheduler rrSheduler = new RRSheduler();
        rrSheduler.addVMAllocation(new VMAllocation(0, 4, 0));
        rrSheduler.addVMAllocation(new VMAllocation(1, 4, 0));
        rrSheduler.addVMAllocation(new VMAllocation(2, 2, 0));
        rrSheduler.addVMAllocation(new VMAllocation(3, 2, 0));
        rrSheduler.addVMAllocation(new VMAllocation(4, 1, 0));

        VMAllocation nextAllocation = null;
        while ((nextAllocation = rrSheduler.getNextFreeVMAllocation()) != null) {
            System.out.println(nextAllocation);
            rrSheduler.cloudSimEventFired(new CloudSimEvent(nextAllocation
                    .getId(), true));
        }

    }
}

我没有像你那样使用地图,但你可能会知道如何解决你的问题。

于 2013-09-17T10:39:04.500 回答
1

应该适合您的代码的函数如下:

public Integer getNextAvailable() {
    Integer machineId = null;
    VMallocation allocation;

    // busyListIsFull is a volatile variable that has to be shared between the 2 classes:
    // the one that contains getNext... and the one that modifies busyList
    //this should be added to the code that modifies busyList
    /*
    if(busyList.containsAll(mapAll.keySet())) {
    busyListIsFull = true;
    notifyAll();
    }
     */

    // all machines are busy
    while(busyListIsFull) {
        try {
            wait();
        } catch (InterruptedException e) {

        }
    }
    busyListIsFull = false;
    notifyAll();

    for(Map.Entry<Integer, VMallocation> entry: mapAll.entrySet()) {
        machineId = (Integer)(entry.getKey());
        allocation = (VMallocation)(entry.getValue());
        // allocate the next machineId if it is not busy and has available allocations
        if(!busyList.contains(machineId) &&
                allocation.getCurrentAlloc() < allocation.getMaxAlloc()) {
            System.out.println("allocating machineId:" + machineId);
            allocation.setCurrentAlloc(allocation.getCurrentAlloc() + 1);
            if(machineId != null) {
                return machineId;
            }
        }
    }
    // no machineId was returned if code execution gets here, so no
    //resource was available; now free them all
    for(Map.Entry<Integer, VMallocation> entry: mapAll.entrySet()) {
        allocation = (VMallocation)(entry.getValue());
        allocation.setCurrentAlloc(0);
    }
    // return first available machine
    return getNextAvailable();
}
于 2013-09-17T09:45:35.137 回答