进程调度之动态优先权算法

本文探讨了动态优先权算法在进程调度中的实现,通过举例说明算法原理。作者强调了随机生成进程的优先数和动态调整数值的重要性,并分析了不同数值比例对调度策略的影响。文中详细介绍了程序设计思路,包括如何创建表示运行进程的时间片数组,以及如何处理没有进程运行的时间片。此外,还解释了时间与数组下标的一致性以及进程编号的对应关系。关键程序段展示了如何找出并更新优先数最高的进程。最后,作者提到了初始化进程到达时间的重要性以及总时间可能不等于进程需求时间累加的问题。

首先,我们要了解动态优先权算法。

举一个例子:

进程名到达时间运行时间优先数
A045
B223
C354
D526

其中优先数越大优先权越高,每运行一个时间片优先数减3。

既然要模拟动态优先权算法,每个进程的到达时间,运行时间和优先数都应该是随机的,并且满足一些条件:

  1. 到达时间大于等于0
  2. 运行时间大于等于1
  3. 优先数之间的差值与优先数动态调整的数值之间要适当
  • 若优先数动态调整的数值远大于优先数之间的差值,则动态优先权算法变成时间片轮转算法
  • 若优先数之间的差值远大于优先数动态调整的数值,则动态优先权算法变成先来先服务算法

按理来说应该是先随机出各进程的优先数,再根据优先数之间的差值决定优先数动态调整的数值。
但是为了模拟方便,我们可以先决定优先数动态调整的数值,将其作为参数,再由这个参数随机出各进程的优先数。此段内容对应:

pcs[i].setPriorityValue(dynamicLevel);// 保证动态调整的值合理
运行结果是怎样的

我想创建一个int数组,其中每个元素对应一个时间片,表示该时间片是哪个进程正在运行。
得到这样一个数组之后,其它信息都可以由它推出。

int数组的长度是总时间,总时间为进程需求时间的累加。
对吗?

在整个过程中,总会出现某个时间片内没有进程运行的情况,比如进程最早到达时间是3,那么前3个时间片(如有疑义见显示的统一化)就是没有进程运行的。
所以在程序里需要计算“真正的”总时间。

由于“真正的”总时间需要遍历得到,得到总时间之后才可以创建数组再次遍历计算,所以这一部分相当于遍历了两次。

第一次:

for (int nowTime = 0; nowTime < allTime; nowTime++) {
			boolean isPosZero = true;
			for (int i = 0; i < n; i++) {
				if (pcs[i].timeCost > 0 && nowTime >= pcs[i].arriveTime) {
					isPosZero = false;
				}
			}
			if (isPosZero) {
				allTime++;
			}
		}

第二次:

for (int nowTime = 0; nowTime < allTime; nowTime++) {
			int pos = -1;
			int compare = -dynamicLevel * (nowTime);// 假设初始优先权为正,优先权可以减至负数,该式保证compare的值始终最小
			for (int i = 0; i < n; i++) {
				if (pcs[i].timeCost > 0 && nowTime >= pcs[i].arriveTime) {
					if (compare < pcs[i].priorityValue) {
						compare = pcs[i].priorityValue;
						pos = i;
					}
				}
			}
			monitor[nowTime] = pos + 1;
			if (pos > -1) {
				pcs[pos].priorityValue -= dynamicLevel;
				pcs[pos].timeCost--;
			}
		}
显示的统一化

我的程序里有两个地方用到了数组,一是时间,二是进程。

时间方面,如果一个时间片代表一秒,到达时间为0指的是在0秒初某进程到达。(我在写代码的时候被高中物理带偏了,如果说第0个时间片太别扭了)
故上文前3个时间片指的是0-1,1-2,2-3。
这样一来时间片数就和数组元素的下标一致了。

进程方面,第0个元素对应进程1,所以需要一些调整。

pcs[i].show1(String.valueOf(i + 1));

show1方法展示的进程名就是参数名,所以将int型的i+1转换成String类

monitor[nowTime] = pos + 1;// 若nowTime有进程运行,则显示进程名;否则显示0.

若无进程运行,pos为-1,所以显示0。

关键程序段
if (compare < pcs[i].priorityValue) {
						compare = pcs[i].priorityValue;
						pos = i;
					}

找出优先数最大的进程,记录它的位置。

if (pos > -1) {
				pcs[pos].priorityValue -= dynamicLevel;
				pcs[pos].timeCost--;
			}

若pos>-1,说明有进程运行了,将运行的进程的优先数减去固定的值,进程的运行时间减1。

完整代码

语言:Java
test.java

package processScheduling;

public class test {
	public static void main(String[] args) {
		Solution S = new Solution();
		// 动态优先权法
		System.out.println("Dynamic Priority Value Algorithm");
		int[] p = S.dynamicPriorityValue(5, 3);
		for (int i = 0; i < p.length; i++) {
			System.out.println(p[i]);
		}
	}
}

Solution.java

package processScheduling;

public class Solution {
	public int[] dynamicPriorityValue(int n, int dynamicLevel) {
		process[] pcs = new process[n];
		int allTime = 0;
		for (int i = 0; i < n; i++) {
			pcs[i] = new process();// 这步一定要有,不然会报错
			pcs[i].setPriorityValue(dynamicLevel);// 保证动态调整的值合理
			allTime += pcs[i].timeCost;// 总时间为进程需求时间的累加
			pcs[i].show1(String.valueOf(i + 1));
		}
		
		// 若所有时间片都有进程在运行队列,则总时间为进程需求时间的累加;
		// 若某一时间片内就绪队列中无进程,则总时间+1;
		for (int nowTime = 0; nowTime < allTime; nowTime++) {
			boolean isPosZero = true;
			for (int i = 0; i < n; i++) {
				if (pcs[i].timeCost > 0 && nowTime >= pcs[i].arriveTime) {
					isPosZero = false;
				}
			}
			if (isPosZero) {
				allTime++;
			}
		}
		int[] monitor = new int[allTime];
		for (int nowTime = 0; nowTime < allTime; nowTime++) {
			int pos = -1;
			int compare = -dynamicLevel * (nowTime);// 假设初始优先权为正,优先权可以减至负数,该式保证compare的值始终最小
			for (int i = 0; i < n; i++) {
				if (pcs[i].timeCost > 0 && nowTime >= pcs[i].arriveTime) {
					if (compare < pcs[i].priorityValue) {
						compare = pcs[i].priorityValue;
						pos = i;
					}
				}
			}
			monitor[nowTime] = pos + 1;// 若nowTime有进程运行,则显示进程名;否则显示0.
			if (pos > -1) {
				pcs[pos].priorityValue -= dynamicLevel;
				pcs[pos].timeCost--;
			}
		}
		return monitor;
	}

process.java

package processScheduling;

import java.util.Random;

public class process {
	int timeCost = (Math.abs(new Random().nextInt())) % 20 + 1;
	int arriveTime = (Math.abs(new Random().nextInt())) % 10;
	int priorityValue = 0;

	void setPriorityValue(int num) {
		priorityValue = (Math.abs(new Random().nextInt())) % num + 1;
	}
	
	void show1(String name) {
		System.out.println("Process " + name + " costs " + timeCost + ",arrives at " + arriveTime
				+ " and its initial priority values " + priorityValue + ".");
	}

}
注释
pcs[i] = new process();// 这步一定要有,不然会报错

这步我一开始也搞不明白,后来看了一个例子就明白了

public class test {
	public static void main(String[] args) {
		String []St= new String[5];
		for(int i=0;i<5;i++) {
			System.out.println(St[i]);//[^1]
		}
	}
	String Str=new String();
		System.out.println(Str);
		System.out.println("为了方便展示");
}

运行结果是

null
null
null
null
null

为了方便展示
后记

我的程序没有将最早到达时间设置成0,事实上这个操作是有意义的,因为0在这里表示的是一个相对时间,代表第一个进程到达的时间。
这个操作只要在所有进程初始化之后,遍历得到最小的到达时间,然后将所有到达时间减去这个值就可以了。
但是这个操作不能避免总时间不一定为进程需求时间的累加的问题。如果第一个进程结束得早,第二个进程来得晚,这个问题还存在。

我选择将优先数大数作为高优先权,事实上可以将优先数小数作为高优先权,这样的好处是可以避免出现负的优先数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qlanBy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值