轮转调度算法和动态优先级调度算法

         在多道程序环境下,内存中着多个进程,进程数目往往多于处理机数目,这时候我们就要针对该问题设计某种算法,动态地将处理机分配给处于就绪状态的一个进程。进程的调度算法有很多,例如先来先服务调度算法(FCFS),短作业优先算法(SJF),时间片轮转算法(RR)和优先级算法,这里我将通过代码的方式主要介绍轮转调度算法(RR)和动态优先级调度算法.

       首先介绍下轮转调度算法:

        A.轮转法的基本原理:

           在轮转法(RR)法中,系统将所有的就绪进程按FCFS策略排成一个就绪队列。系统可设置每隔一定时间(如30ms)便产生一次中断,去激活进程调度程序进行调度,把CPU分配给队首进程,并令其执行一个时间片。当它运行完毕后,又把处理机分配给就绪队列中新的队首进程,也让其执行一个时间片片。这样,就可以保证就绪队列中的所有进程在确定的时间段内,都能获得一个时间片的处理机时间。

       B.进程切换时机:

          在轮转调度算法中,应在何时进行进程的切换,可分成两种情况:1.若一个时间片尚未用完,正在运行的进程便已经完成,就立即激活调度程序,将它从就绪队列中删除,在调度就绪队列中队首的进程运行,并启动一个新的时间片。2.在一个时间片用完时,计时器中断处理程序被激活。如果进程尚未运行完毕,调度程序将把它送往就绪队列的末尾。

       C.时间片大小的确定:

          在轮转算法中,时间片的大小对系统性能有着很大的影响。若选择很小的时间内片,将有利于短作业,因为它能在该时间片内完成。但时间片小,意味着会频繁地执行进程调度和进程上下文的切换,这无疑会增加系统的开销。反之,若事件片选择的太长,且为使每个进程都能在一个时间片内完成,轮转算法便退化为FCFS算法,无法满足短作业和交互式用户的需求。一个较为可取的时间片大小是略大于一次典型的交互所需要的时间,使大多数交互式进程能在一个时间片内完成,从而可以获得很小的响应时间。

        D.算法流程图:

                                  轮转调度算法和动态优先级调度算法_第1张图片

         E.实现代码:

class PCBRR{
	public int id;
	public int everyTimeCount;
    public int alreadyCpuTime;
    public int stillNeedCpuTime;
    
    public PCBRR(int id, int everyTimeCount, int alreadyCpuTime, int stillNeedCpuTime) {
		super();
		this.id = id;
		this.everyTimeCount = everyTimeCount;
		this.alreadyCpuTime = alreadyCpuTime;
		this.stillNeedCpuTime = stillNeedCpuTime;
	}
    
    @Override
	public String toString() {
		return "进程号:" + this.id + " 已占有的CPU时间:" + this.alreadyCpuTime + " 还需的CPU时间:"
	         + this.stillNeedCpuTime+" 每次轮转的时间片数:"+this.everyTimeCount;
	}
}



private static void RoundRobin() {
		LinkedList pcbs = new LinkedList();
		System.out.println("请输入进程数目:");
		int num = scanner.nextInt();
		System.out.println("系统为这" + num + "个进程随机分配优先级数和运行所需的CPU数.以下是进程的详细情况:");
		for (int i = 0; i < num; i++) {
			//产生n个进程(id号,每次轮转的时间片数,已占用的CPU时间片数,仍需要的时间片数)
			pcbs.addLast(new PCBRR(i,random.nextInt(5) + 1, 0, random.nextInt(30) + 1));
		}
		Iterator iterator = pcbs.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		System.out.println();System.out.println();
		System.out.println("下面开始进行轮转法进程调度算法---------------");
		LinkedList donePCB = new LinkedList();
		int current = 1;
		while(pcbs.size()>0)
		{
			System.out.println("当前正在执行第" + (current++) + "次时间片");
			PCBRR pcbrr=pcbs.removeFirst();
			System.out.println("将要执行的进程为 ----"+pcbrr);
			pcbrr.alreadyCpuTime++;
			pcbrr.stillNeedCpuTime--;
			if(pcbrr.stillNeedCpuTime<=0)    //进程总体运行结束
			{
				donePCB.addLast(pcbrr.id);
			}
			else if(pcbrr.alreadyCpuTime>=pcbrr.everyTimeCount)
			{         //进程已经运行完其所分配的每次轮转时间片,将其放在轮转队尾
				pcbrr.alreadyCpuTime=0;
				pcbs.addLast(pcbrr);
			}
	//进程位运行完其所分配的每次轮转时间片,下面仍将继续运行该进程
			else {
				pcbs.addFirst(pcbrr);
			}
			System.out.println("执行完这个时间片后系统轮转队列中的所有进程的情况如下:");
			if(pcbs.size()>0)
			{
				Iterator temp = pcbs.iterator();
				while (temp.hasNext()) {
					System.out.println(temp.next());
				}
			}
			else
				System.out.println("空");
			
			
			System.out.println("已经完成的进程有:(用进程号表示)");
			Iterator itera = donePCB.iterator();
			if (!itera.hasNext()) {
				System.out.println("无");
		       System.out.println();System.out.println();
			   System.out.println();System.out.println();
			   continue;
			}
			
			while (itera.hasNext()) {
				System.out.print(itera.next()+" ");
			}
			System.out.println();System.out.println();
			System.out.println();System.out.println();
		}
		System.out.println("轮转法进程调度算法结束---------------");
	}

         接下来介绍动态优先级调度算法:

            A.基本原理;               

     动态优先级调度算法是指在创建进程之初,先赋予其一个优先级,然后其值随着进程的推进或等待时间的增加而改变,以便获得更好的调度性能。例如,可以规定在就绪队列中的进程随其等待的时间的正常,使其优先级相应提高。若所有的进程都具有相同的优先级初值,则最先进入就绪队列的进程会因为其优先级变得最高,而优先获得处理机,这相当于FCFS算法。若所有的就绪进程具有各不相同的优先级初值,那么对于优先级初值低的进程,在等待了足够的时间后,也可以获得处理机。

            B.算法流程图:

                                         轮转调度算法和动态优先级调度算法_第2张图片

                 C.实现代码:

class PCBPM implements Comparable {
 	public int id;
	public int pority;
	public int cputime;

	public PCBPM(int id, int pority, int cputime) {
		super();
		this.id = id;
		this.pority = pority;
		this.cputime = cputime;
	}
	@Override
	public int compareTo(Object obj) {
		PCBPM pcb = (PCBPM) obj;
		if (pcb.pority >= this.pority)
			return 1;
		return -1;
	}
	@Override
	public String toString() {
		return "进程号:" + this.id + " 优先级:" + this.pority + " 所需的CPU时间:" + this.cputime;
	}
}

private static void PriorityMethod() {
		TreeSet pcbs = new TreeSet();
		System.out.println("请输入进程数目:");
		int num = scanner.nextInt();
		System.out.println("系统为这" + num + "个进程随机分配优先级数和运行所需的CPU数.以下是进程的详细情况:");
		for (int i = 0; i < num; i++) {
			pcbs.add(new PCBPM(i, random.nextInt(60) + 1, random.nextInt(20) + 1));
		}
		Iterator iterator = pcbs.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		System.out.println();System.out.println();
		System.out.println("下面开始进行优先权进程调度算法---------------");
		int current = 1;
		LinkedList donePCB = new LinkedList();
		while (pcbs.size() > 0) {
			System.out.println("当前正在执行第" + (current++) + "次时间片");
			PCBPM pcb = pcbs.pollFirst();
			System.out.println("将要执行的进程为 ----" + pcb);
			pcb.cputime--;
			pcb.pority -= 3;
			if (pcb.cputime <= 0)
				donePCB.addLast(pcb.id);
			else
				pcbs.add(pcb);
			System.out.println("执行完这个时间片后系统优先进程队列中的所有进程的情况如下:");
			if (pcbs.size() > 0) {
				Iterator temp = pcbs.iterator();
				while (temp.hasNext()) {
					System.out.println(temp.next());}}
			else
				System.out.println("空");
			System.out.println("已经完成的进程有:(用进程号表示)");
			Iterator itera = donePCB.iterator();
			if (!itera.hasNext()) {
				System.out.println("无");
		       System.out.println();System.out.println();
			   System.out.println();System.out.println();
			   continue;
			}
			while (itera.hasNext()) {
				System.out.print(itera.next()+" ");
			}
			System.out.println();System.out.println();
			System.out.println();System.out.println();
		}
		System.out.println("优先权进程调度算法结束
---------------");}
               


    接下来是一些整合工作,我按照以下的流程方式将两种调度算法进行整合:

轮转调度算法和动态优先级调度算法_第3张图片

      程序入口和相关静态对象的代码如下:

        public static Scanner scanner = new Scanner(System.in);
	public static Random random = new Random();

	public static void main(String[] args) {

		System.out.println("请选择进程调度的方法:");
		System.out.println("1).优先权法          2).轮转法");
		int choice = scanner.nextInt();
		if (choice == 1)
			PriorityMethod();
		else
			RoundRobin();
	}


      实验结果截图:

         1).对于轮转调度算法:

轮转调度算法和动态优先级调度算法_第4张图片

轮转调度算法和动态优先级调度算法_第5张图片

。。。。。。。(由于截图过多,这里仅显示开头和结尾数据)

轮转调度算法和动态优先级调度算法_第6张图片


        2).对于动态优先级调度算法:

   轮转调度算法和动态优先级调度算法_第7张图片

轮转调度算法和动态优先级调度算法_第8张图片

。。。。。。。(由于截图过多,这里仅显示开头和结尾数据)

轮转调度算法和动态优先级调度算法_第9张图片



PS:自发表了第一篇的银行家算法的博文,慢慢有了阅读量,小小的成就感爆棚,之后就顺手写下操作系统中比较重要的两种进程调度算法,动手写代码,对算法的理解肯定是有帮助的。最后,还是那句话,博客小白还望各位大佬不吝赐教~

你可能感兴趣的:(轮转调度算法和动态优先级调度算法)