Schedule.java

import java.util.*;

/**
 * Created by Lairai on 2018/1/14.
 */
public class Schedule {

    private final static String SEPERATOR = "*****************************";

    /*调度算法*/
    private final static int FCFS = 1;
    private final static int SJF = 2;

    /*内存区总大小*/
    private static int size;

    /*预先输入的所有作业,按进入时间排序*/
    private List<Job> jobList;
    int newestJobIndex = 0;


    /*作业队列, 列表*/
    private Queue<Job> waitingQueue;
    private Queue<Job> loadedQueue;
    private Job currentExecutingJob;
    private Queue<Job> scheduleOrderQueue;

    /*空闲区链表头*/
    private Node head;

    /*系统时间*/
    private Time systemTime;

    public Schedule(int size, int algorithm) {

        this.size = size;
        jobList = new ArrayList<>();


        if (algorithm == FCFS) {
            waitingQueue = new ArrayDeque<>();
            loadedQueue = new ArrayDeque<>();
        } else {
            waitingQueue = new PriorityQueue<>((x, y) -> {
                return x.getErt() - y.getErt();
            });
            loadedQueue = new PriorityQueue<>((x, y) -> {
                return x.getErt() - y.getErt();
            });
        } /*短作业优先的情况下使用小顶堆*/

        promptInput();//提示用户输入作业信息,初始化JobList

        /*系统时间初始化为第一个作业的提交时间*/
        Time startTime = jobList.get(0).getEt();
        systemTime = new Time(startTime.getHour(), startTime.getMinute());

        currentExecutingJob = null;
        scheduleOrderQueue = new ArrayDeque<>();
        head = new Node(0, size, new Node(0, size, null));
    }

    public void work() {

        while (true) {

            checkNewJob();

            /*所有作业执行完毕后结束此次调度*/
            if (newestJobIndex == jobList.size() && currentExecutingJob == null) break;

            /*如果当前没有作业在执行*/
            if (currentExecutingJob == null) {
                if (!loadedQueue.isEmpty()) {
                    currentExecutingJob = pickJobFromMemory();
                } else {
                    systemTime.increaseByMinute();
                    continue;//处理机等待一分钟
                }
            }

            executeCurrentJob();

        }
    }

    /*添加当前时刻提交的所有作业到等待列表*/
    private void checkNewJob() {
        while (true) {
            if (newestJobIndex == jobList.size()) break;

            Job job = jobList.get(newestJobIndex);

            /*如果当前时刻有新作业提交*/
            if (job.getEt().equals(systemTime)) {

                ++newestJobIndex;

                Node space = enoughSpace(job);
                /*如果能装入内存则使其装入内存*/
                if (space != null) {
                    allocateMemory(space, job.getNc());
                    loadedQueue.add(job);
                }
                /*否则装入等待队列*/
                else waitingQueue.add(job);
            } else break;
        }
    }

    /**
     * 提示用户输入作业信息
     */
    private void promptInput() {
        System.out.println("Input Job formatted as \"A(job name),8:06(entry time),42(expected runnning time),15(needed capacity in MB)\"");
        System.out.println("Input \'#\' to end input");
        Scanner scanner = new Scanner(System.in);
        String line;
        while (true) {
            line = scanner.nextLine();
            if ("#".equals(line)) break;
            else jobList.add(getJob(line));
        }
        scanner.close();
    }

    /**
     * 根据字符串构造出一个作业
     */
    private Job getJob(String s) {
        String[] parameters = s.split(",");
        if (parameters.length != 4) return null;
        String[] time = parameters[1].split(":");
        return new Job(parameters[0], Integer.parseInt(time[0]), Integer.parseInt(time[1]), Integer.parseInt(parameters[2]), Integer.parseInt(parameters[3]));
    }

    /**
     * @return 指向能容纳x的空闲区的结点
     */
    private Node enoughSpace(Job x) {
        if (x == null || head.freeSize < x.getNc()) return null;
        else {
            int len = x.getNc();
            Node p = head;
            while (p.next != null) {
                if (p.next.freeSize >= len) {
                    x.setIa(p.next.initialAddress);
                    return p;
                }
                p = p.next;
            }
            return null;
        }
    }

    /**
     * 为新进入内存的作业分配空间
     * @param p 分配区间的前驱结点
     * @param len 所分配的长度
     */
    private void allocateMemory(Node p, int len) {
        if (p.next.freeSize > len) {
            p.next.freeSize -= len;
            p.next.initialAddress += len;
        } else {
            p.next = p.next.next;
        }
        head.freeSize -= len;
    }

    /*从装入内存的作业里调度一个可以投入运行的作业*/
    private Job pickJobFromMemory() {
        Job job = loadedQueue.poll();
        if (job != null) {
            job.setSt(new Time(systemTime.getHour(), systemTime.getMinute()));
            System.out.println("On job " + job.getName() + " gets scheduled at " + systemTime + ", partition state: " + partitionState());
            scheduleOrderQueue.add(job);
        }
        return job;
    }

    /*尽可能的从等待队列里往内存载入作业*/
    private void loadFromWaitingQueue() {
        Iterator<Job> iterator = waitingQueue.iterator();
        while (iterator.hasNext()) {
            Job job = iterator.next();
            Node space = enoughSpace(job);
            if (space != null) {
                loadedQueue.add(job);
                allocateMemory(space, job.getNc());
                iterator.remove();
            }
        }
    }

    private String partitionState() {
        Node p, q;
        p = head.next;
        StringBuffer buffer = new StringBuffer(100);
        buffer.append("Free Partition: ");
        while (p != null) {
            buffer.append(" [" + p.initialAddress + ", "
                    + (p.initialAddress + p.freeSize - 1) + "]");
            p = p.next;
        }
        return buffer.toString();
    }

    private void reclaimMemory(Job job) {
        Node front = head, back = front.next;
        int ia = job.getIa();

        Node j = new Node(ia, job.getNc(), null);

        while (front != null) {
            if (front.initialAddress <= ia && (back == null || back.initialAddress >= ia)) {
                break;
            } else {
                front = back;
                back = front.next;
            }
        }

        if (adjacent(j, back)) {
            j = merge(j, back);
        } else {
            j.next = back;
        }

        if (adjacent(front, j)) {
            front = merge(front, j);
        } else {
            front.next = j;
        }

        head.freeSize += job.getNc();
    }

    private boolean adjacent(Node front, Node back) {
        if (back == null || front == head) return false;
        return (front.initialAddress + front.freeSize == back.initialAddress);
    }

    /**
     * 合并两个相邻的空闲区
     * @return 合并后的空闲区节点
     */
    private Node merge(Node front, Node back) {
        front.freeSize += back.freeSize;
        front.next = back.next;
        return front;
    }

    private String[] getOutputInfo(Queue<Job> orderQ){
        Iterator<Job> iterator = orderQ.iterator();
        StringBuffer orderBuffer = new StringBuffer(20);
        StringBuffer timeBuffer = new StringBuffer(200);
        Job job;
        while (iterator.hasNext()) {
            job = iterator.next();
            orderBuffer.append(job.getName() + " ");
            timeBuffer.append("Job " + job.getName() + " : Starting Time: " + job.getSt() + " Finished Time: " + job.getFt() + '\n');
        }
        String[] ans =  {orderBuffer.toString(), timeBuffer.toString()};
        return ans;
    }

    private void executeCurrentJob() {

        systemTime.increaseByMinute();

        /*让当前正在执行的作业执行一分钟*/
        currentExecutingJob.executeByMinite();

        /*如果执行完毕*/
        if (currentExecutingJob.finished()) {
            currentExecutingJob.setFt(new Time(systemTime.getHour(), systemTime.getMinute()));
            currentExecutingJob.calculateTurnover();
            reclaimMemory(currentExecutingJob);//回收执行完毕的作业的空间
            currentExecutingJob = pickJobFromMemory();
            loadFromWaitingQueue();
        }
    }

    public void printScheduleInfo() {
        /*输出这批作业的调度信息*/
        String[] info = getOutputInfo(scheduleOrderQueue);
        System.out.println("Schedule Order: " + info[0]);
        System.out.println("Schedule of Each Job:\n" + info[1]);
        double mtt = 0, mwt = 0;//平均周转时间和平均带权周转时间
        for (Job job : scheduleOrderQueue) {
            mtt += job.getTt();
            mwt += job.getWt();
        }
        mtt /= newestJobIndex;
        mwt /= newestJobIndex;
        System.out.println(SEPERATOR + "\nMean Turnover Time: " + mtt + " minutes.");
        System.out.println(SEPERATOR + "\nMean Weighted Turnover Time: " + mwt + " minutes.");
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容