树中的内存泄漏?

时间:2011-06-18 19:01:32

标签: java memory-management

我正在运行双机作业调度算法模拟。目前我在2台机器上,每台10个工作岗位,而且我已经没有内存......我的任务目标是运行2台机器,每台工作20个;从它的外观来看,我真的离这个目标很远。所以我希望你能给我内存管理的所有技巧和窍门。请随意扔掉任何东西。

定义作业属性的类

public class Job {
final static int WAITING = 0;
final static int ASSIGNED = 1;
final static int COMPLETE = 2;

int num;
int machine;
int time;
int weight;
int due;
int resUse;
int resGain;

int parent;
int status = 0;//0:incomplete 1:assigned 2:complete

public Job() {
}

public Job(int num, int machine, int time, int weight, int due, int resUse, int resGain, int parent, int status) {
    super();
    this.num = num;
    this.time = time;
    this.machine = machine;
    this.weight = weight;
    this.due = due;
    this.resUse = resUse;
    this.resGain = resGain;
    this.parent = parent;
    this.status = status;
}


public String toString() {
    return "n=" + num + " m=" + machine + " t=" + time + " w=" + weight + " d=" + due + " a=" + resUse + " b=" + resGain + " p=" + parent + " s=" + status;
}
}

这是我的“节点”类

public class Machine {

int job[] = new int[Algo.NUM_MACHINES];
int remTime[] = new int[Algo.NUM_MACHINES];
int res = Algo.RESOURCE;
int time = 0;
int tardy = 0;

//Job jobTree[] = new Job[Algo.NUM_JOBS];
ArrayList<Integer> jobsFinished = new ArrayList<Integer>();

int id;
boolean visited = false;
Machine parent = this;//so that root node points to himself
ArrayList<Machine> children = new ArrayList<Machine>();

int duplicate = 0;//duplicate (sj-sj-sj-sj-...) flag

public Machine() {
    jobsFinished.add(0);
}

/**
 * cloning constructor
 * @param shadow
 */
public Machine(Machine shadow) {
    this.job = shadow.job.clone();
    this.remTime = shadow.remTime.clone();
    this.res = shadow.res;
    this.time = shadow.time;
    this.tardy = shadow.tardy;
    this.parent = shadow;
    this.duplicate = shadow.duplicate;
    this.jobsFinished.addAll(shadow.jobsFinished);

}

/**
 * method used to obtain machine state
 * @return 0 if both machines are idle, 1 if one machine is busy, and 2 if both machines are
 *         busy
 */
public int getMachineState() {
    if (remTime[0] == 0 && remTime[1] == 0)
        return 0;
    else if (remTime[0] != 0 && remTime[1] != 0)
        return 2;
    else
        return 1;
}

public String toString() {
    String jobStr = " job[]=";
    for (int i = 0; i < job.length; i++)
        jobStr += job[i] + " ";
    String timeStr = "rem[]=";
    for (int i = 0; i < remTime.length; i++)
        timeStr += remTime[i] + " ";

    return "id=" + id + jobStr + timeStr + "time=" + time + " parent=" + parent.id + " tardy=" + tardy + " res=" + res + " dup=" + duplicate;
}
}

我提出了写得不好的算法:

public class Algo {
final static int NUM_MACHINES = 2;
final static int NUM_JOBS = 20 + 1;
final static int RESOURCE = 15;

final int LOWER_BOUND = 1;
final int DUPLICATE = 1;

/*
p11 = 3    w11 = 7     d11 = 16    alpha = 3   beta = 6
p12 = 6    w12 = 1     d12 = 11    alpha = 7   beta = 16
p13 = 8    w13 = 3     d13 = 15    alpha = 8   beta = 3
p21 = 5    w21 = 6     d21 = 8     alpha = 7   beta = 3
p22 = 4    w22 = 10    d22 = 6     alpha = 6   beta = 2
 */
final Job jobTree[] = { new Job(0, 0, 999, 0, 999, 999, 0, 0, Job.COMPLETE),
        new Job(1, 0, 95, 1, 246, 9, 8, 0, Job.WAITING),
        new Job(2, 0, 10, 6, 184, 8, 6, 1, Job.WAITING),
        new Job(3, 0, 63, 4, 367, 3, 9, 2, Job.WAITING),
        new Job(4, 0, 71, 9, 353, 18, 19, 3, Job.WAITING),
        new Job(5, 0, 10, 1, 305, 7, 14, 4, Job.WAITING),
        new Job(6, 0, 97, 7, 239, 3, 2, 5, Job.WAITING),
        new Job(7, 0, 83, 2, 132, 4, 5, 6, Job.WAITING),
        new Job(8, 0, 24, 2, 354, 5, 10, 7, Job.WAITING),
        new Job(9, 0, 59, 5, 371, 15, 2, 8, Job.WAITING),
        new Job(10, 0, 10, 2, 260, 1, 15, 9, Job.WAITING),

        new Job(11, 1, 36, 7, 145, 3, 13, 0, Job.WAITING),
        new Job(12, 1, 88, 6, 270, 13, 19, 11, Job.WAITING),
        new Job(13, 1, 30, 4, 229, 10, 16, 12, Job.WAITING),
        new Job(14, 1, 47, 7, 118, 11, 6, 13, Job.WAITING),
        new Job(15, 1, 88, 3, 180, 11, 19, 14, Job.WAITING),
        new Job(16, 1, 40, 2, 141, 1, 9, 15, Job.WAITING),
        new Job(17, 1, 18, 6, 245, 17, 5, 16, Job.WAITING),
        new Job(18, 1, 18, 8, 250, 17, 18, 17, Job.WAITING),
        new Job(19, 1, 6, 6, 207, 8, 6, 18, Job.WAITING),
        new Job(20, 1, 53, 5, 159, 5, 6, 19, Job.WAITING) };

ArrayList<Machine> mLeastTardy = new ArrayList<Machine>();
Machine mRoot;
int index = 0;
int minTardy = 99999;

ArrayList<HashMap> mDuplicate = new ArrayList<HashMap>();

public void init() {
    System.out.println("advAlgo3");
    mRoot = new Machine();
    mRoot.id = index++;
    //mState.add(root);
}

public void run() throws Exception {
    init();

    //int minTardyStateIndex = 0;

    Machine state = mRoot;
    Machine minTardyState = null;

    //begin algorithm
    while (true) {
        //System.out.println("run() " + state);
        if (state.visited == false) {

            switch (state.getMachineState()) {
                case 0://both machines are free
                    for (Job job : jobTree)
                        scheduleJob(state, job);
                    break;
                case 1:
                    scheduleWork(state);
                    for (Job job : jobTree)
                        scheduleJob(state, job);
                    break;
                case 2:
                    scheduleWork(state);
                    break;
            }

            state.visited = true;
        }

        //begin min-tardy analysis
        if (state.jobsFinished.size() == NUM_JOBS) {//if all jobs are finished
            if (state.tardy < minTardy) {//if the schedule is least tardy
                minTardyState = state;
                minTardy = minTardyState.tardy;

                mLeastTardy.clear();//renew the leastTardy path
                while (minTardyState.id != 0) {
                    mLeastTardy.add(minTardyState);
                    minTardyState = minTardyState.parent;
                }
            }
        }

        //garbage collection
        if (state.children.isEmpty()) {//if this is a leaf node (no children)
            state.parent.children.remove(state);
        }

        //traverse to the next node
        Machine nextState = state.parent;//default is to traverse up
        for (Machine childState : state.children) {
            if (childState.visited == false) {//but if you can find a child that hasn't been visited yet
                nextState = childState;//traverse down
                break;
            }
        }
        state = nextState;

        //when all nodes have been traversed
        if (nextState.id == 0) {//if traverse back to root
            boolean finish = true;
            for (Machine child : nextState.children) {
                if (child.visited == false)//if root still has an unvisited child
                    finish = false;
            }
            if (finish == true) {
                break;
            }
        }
    }//end algorithm

    /*
    //begin backward analysis
    ArrayList<Machine> minTardy = new ArrayList<Machine>();
    while (minTardyState.id != 0) {
        minTardy.add(minTardyState);
        minTardyState = minTardyState.parent;
    }*/

    //print path & gnatt chart
    String gnattChart[] = new String[Algo.NUM_MACHINES];
    for (int i = 0; i < gnattChart.length; i++)
        gnattChart[i] = "";
    state = mRoot;

    for (int i = mLeastTardy.size() - 1; i >= 0; i--) {
        Machine nextState = mLeastTardy.get(i);
        System.out.println(nextState);

        for (int j = 0; j < Algo.NUM_MACHINES; j++) {
            if (nextState.remTime[j] == 0) {
                int t = nextState.time - state.time;
                for (int k = 0; k < Algo.NUM_MACHINES; k++) {
                    for (int l = 0; l < t; l++) {
                        if (state.job[k] < 10)
                            gnattChart[k] += state.job[k];
                        else {
                            gnattChart[k] += '#';
                        }
                    }
                }
            }
        }
        state = nextState;
    }
    System.out.println("# of Nodes=" + index);
    System.out.println("# of Duplicates=" + mDuplicate.size());
    System.out.println("Gnatt chart:");
    for (String gnatt : gnattChart) {
        System.out.println(gnatt);
    }

    //generateGraph();

}

private void scheduleJob(Machine parent, Job job) {
    if (parent.res >= job.resUse) {//if there's enough resource to run the job
        if (parent.remTime[job.machine] == 0) {//if the dedicated machine is idle
            if (parent.jobsFinished.contains(job.parent)) {//if the preceeding job is complete
                if (!parent.jobsFinished.contains(job.num)) {//but this isn't

                    //create a copy of the current state
                    Machine child = new Machine(parent);
                    child.id = index++;
                    //assign the job to the machine
                    child.job[job.machine] = job.num;
                    //set the machine's running time
                    child.remTime[job.machine] = job.time;
                    //deduct the resources
                    child.res -= job.resUse;
                    //update the job tree
                    //child.jobTree[job.num].status = Job.ASSIGNED;
                    //duplicate analysis
                    if (DUPLICATE == 1) {
                        child.duplicate++;
                        if (child.duplicate == NUM_MACHINES) {//if sj-sj
                            boolean new_dup = true;
                            for (HashMap dupmap : mDuplicate) {//compare against duplicate list
                                if (child.time == (Integer) dupmap.get("time")) {
                                    int num_dup = 0;
                                    for (int jNum : child.job) {
                                        if (((ArrayList<Integer>) dupmap.get("dupJob")).contains(jNum)) {
                                            num_dup++;
                                        } else {
                                            break;
                                        }
                                    }
                                    if (num_dup == NUM_MACHINES) {
                                        child.visited = true;
                                        new_dup = false;
                                        break;
                                    }
                                }
                            }

                            if (new_dup) {//if this is a new combo, append this combo to the duplicate list

                                ArrayList<Integer> dup = new ArrayList<Integer>();
                                for (int jNum : child.job) {
                                    dup.add(jNum);
                                }
                                HashMap dupmap = new HashMap();
                                dupmap.put("time", child.time);
                                dupmap.put("dupJob", dup);
                                //System.out.println(dupmap);
                                mDuplicate.add(dupmap);
                            }
                        }
                    }
                    //
                    parent.children.add(child);
                    //System.out.println("sj() " + child + " # " + job);
                    //add this state to the tree
                    //mState.add(child);
                }
            }
        }
    }
}

private void scheduleWork(Machine parent) {
    //find the machine with the shortest remaining processing time
    int shortestTime = 99999;
    for (int i = 0; i < NUM_MACHINES; i++) {
        if (parent.remTime[i] < shortestTime && parent.remTime[i] != 0) {
            shortestTime = parent.remTime[i];
        }
    }

    //schedule Work node for ALL machines working on a job with the shortest remaining processing time
    for (int i = 0; i < NUM_MACHINES; i++) {
        if (parent.remTime[i] == shortestTime) {//if this machine is working on a job with the shortest remaining processing time
            Job finishingJob = jobTree[parent.job[i]];

            //create a copy of the current state
            Machine child = new Machine(parent);
            child.id = index++;
            //move the time pointer forward
            child.time += shortestTime;
            //increase tardiness
            if (child.time > finishingJob.due) {
                child.tardy += (child.time - finishingJob.due) * finishingJob.weight;
            }
            if (LOWER_BOUND == 1) {
                if (child.tardy > minTardy) {
                    child.visited = true;
                }
            }
            //return resources
            child.res += finishingJob.resGain;
            //free the machine
            child.job[i] = 0;
            for (int j = 0; j < NUM_MACHINES; j++)
                if (child.remTime[j] > 0)
                    child.remTime[j] -= shortestTime;
            //update the job tree
            child.jobsFinished.add(finishingJob.num);
            //reset the duplicate flag
            if (DUPLICATE == 1) {
                child.duplicate = 0;
            }
            //
            parent.children.add(child);
            //System.out.println("sw() " + child);

            //add the state to the tree
            //mState.add(child);
        }
    }
}
/*
    private void generateGraph() throws Exception {
        Undirectgraph ug = new Undirectgraph();
        int stateNum = mState.size();
        ug.createMatrix(stateNum);

        for (int i = 0; i < stateNum; i++) {
            int childNum = mState.get(i).children.size();
            for (int j = 0; j < childNum; j++)
                ug.addEdge(i + 1, mState.indexOf(mState.get(i).children.get(j)) + 1, mState.get(i).children.get(j).tardy);
        }

        System.out.println(ug.toGraphviz());
    }*/
}

最后是执行算法的主类

public class Main {
public static void main(String args[]) throws Exception {
    Algo program = new Algo();
    program.run();
}
}

1 个答案:

答案 0 :(得分:0)

问题解决了,发现了泄漏。只是想回答我自己关闭这个问题。

我通过

删除了一个孩子
    //garbage collection
    if (state.children.isEmpty()) {//if this is a leaf node (no children)
        state.parent.children.remove(state);
    }

每次发生泄漏

    if (some_condition) {
        child.visited = true;
    }

如果某个节点过早地被设置为被访问,我将无法遍历该节点并检查该节点的子节点是否为空。导致节点无法回收。

中提琴。