在多道程序环境下,内存中着多个进程,进程数目往往多于处理机数目,这时候我们就要针对该问题设计某种算法,动态地将处理机分配给处于就绪状态的一个进程。进程的调度算法有很多,例如先来先服务调度算法(FCFS),短作业优先算法(SJF),时间片轮转算法(RR)和优先级算法,这里我将通过代码的方式主要介绍轮转调度算法(RR)和动态优先级调度算法.
首先介绍下轮转调度算法:
A.轮转法的基本原理:
在轮转法(RR)法中,系统将所有的就绪进程按FCFS策略排成一个就绪队列。系统可设置每隔一定时间(如30ms)便产生一次中断,去激活进程调度程序进行调度,把CPU分配给队首进程,并令其执行一个时间片。当它运行完毕后,又把处理机分配给就绪队列中新的队首进程,也让其执行一个时间片片。这样,就可以保证就绪队列中的所有进程在确定的时间段内,都能获得一个时间片的处理机时间。
B.进程切换时机:
在轮转调度算法中,应在何时进行进程的切换,可分成两种情况:1.若一个时间片尚未用完,正在运行的进程便已经完成,就立即激活调度程序,将它从就绪队列中删除,在调度就绪队列中队首的进程运行,并启动一个新的时间片。2.在一个时间片用完时,计时器中断处理程序被激活。如果进程尚未运行完毕,调度程序将把它送往就绪队列的末尾。
C.时间片大小的确定:
在轮转算法中,时间片的大小对系统性能有着很大的影响。若选择很小的时间内片,将有利于短作业,因为它能在该时间片内完成。但时间片小,意味着会频繁地执行进程调度和进程上下文的切换,这无疑会增加系统的开销。反之,若事件片选择的太长,且为使每个进程都能在一个时间片内完成,轮转算法便退化为FCFS算法,无法满足短作业和交互式用户的需求。一个较为可取的时间片大小是略大于一次典型的交互所需要的时间,使大多数交互式进程能在一个时间片内完成,从而可以获得很小的响应时间。
D.算法流程图:
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<PCBRR> pcbs =
new LinkedList<PCBRR>();
-
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<Integer> donePCB =
new LinkedList<Integer>();
-
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.算法流程图:
![](https://i-blog.csdnimg.cn/blog_migrate/57e24752436fad5a7bcad8fb858e119b.png)
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<PCBPM> pcbs =
new TreeSet<PCBPM>();
-
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<Integer> donePCB =
new LinkedList<Integer>();
-
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(
"优先权进程调度算法结束
-
---------------");}
接下来是一些整合工作,我按照以下的流程方式将两种调度算法进行整合:
程序入口和相关静态对象的代码如下:
-
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).对于轮转调度算法:
2).对于动态优先级调度算法:
![](https://i-blog.csdnimg.cn/blog_migrate/1f68dc3aeb29bb211ef9d960a9d1e83c.png)
。。。。。。。(由于截图过多,这里仅显示开头和结尾数据)
PS:自发表了第一篇的银行家算法的博文,慢慢有了阅读量,小小的成就感爆棚,之后就顺手写下操作系统中比较重要的两种进程调度算法,动手写代码,对算法的理解肯定是有帮助的。最后,还是那句话,博客小白还望各位大佬不吝赐教~