磁盘调度管理代码实现(JAVA实现)

习题答案和练习 专栏收录该内容
16 篇文章 8 订阅

1 设计内容

2 分析设计
2.1 算法原理
通过编程实现不同磁盘调度算法。具体要求如下:

1.设定开始磁道号寻道范围,依据起始扫描磁道号和最大磁道号数,随机产生要进行寻道的磁道号序列。(也可以输入一组作业的磁道请求序列)2. 选择磁盘调度算法,显示该算法的磁道访问顺序,计算出移动的磁道总数和平均寻道总数。并输出按选择的算法执行时的磁头移动轨迹。请在以下算法中任意选择两种实现,并对算法性能进行分析对比。
实现提示:
常用的磁盘调度算法简介如下:

1.最短寻道优先算法SSTF:该算法选择这样的进程:其要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短。

2.扫描算法SCAN:首先考虑磁盘请求的磁头移动方向,在方向一致的情况下优先调度与磁头最近的请求。若从内向外扫描,则在到达最外层柱面后,再改变方向从外向内扫描,达到最内层柱面后再重复前面过程;若从外向内扫描,则也在达到最内层后再改变方向。

3.电梯算法: 电梯算法是对扫描算法的一种改进,基本思想是:没有访问请求时磁头不动,有访问请求时磁头来回扫描,每次选择磁头移动方向上离当前磁头位置最近的访问请求进行处理。扫描过程中,若磁头移动方向上仍有访问请求,则继续向同一个方向扫描;若磁头移动方向上不存在访问请求,则改变方向扫描。

4.循环扫描算法CSCAN:CSCAN算法规定磁头单向移动,例如,只是自里向外移动,当磁头移到最外的磁道并访问后,磁头立即返回到最里的欲访问的磁道,亦即将最小磁道号紧接着最大磁道号构成循环,进行循环扫描。
说明:测试数据可以先用教材上例题、习题中的数据,再使用随机数进行测试。

2.2 程序结构
我的这个程序也是用java来实现的,主要是采用了一个switch分支模块,分别有5个分支,前面四个分别对应四个调度算法FCFS、SSTF、SCAN、CSCAN,最后一个分支是提示错误的分支,比如输入的数字不是1-5,分支之前一个if语句如果用户选择5就退出程序。

2.3 数据结构
在这里插入图片描述

2.4 程序流程图
在这里插入图片描述
2.5 关键代码

2.5.1 FCFS关键代码

/**
	 * 先来先服务算法
	 * @param cidao 要访问的磁道数组
	 * @param m
	 */
	void FCFS(int cidao[],int m)   //磁道号数组,个数为m 
{
    int now = -1;     //当前磁道号
    int sum = 0;	 //总寻道长度
    int i;
    float ave=0.0f;   //平均寻道长度
	System.out.println("磁盘请求序列为:");
    for( i=0;i<m;i++)   //按先来先服务的策略输出磁盘请求序列
    {
		System.out.print(cidao[i]+"  ");
    }
	System.out.println();
	System.out.print("请输入当前的磁道号:");
	Scanner input = new Scanner(System.in);
	  now=input.nextInt();
    sum+=Math.abs(cidao[0]-now);//求当前输入磁道和第一要访问磁道的距离
	System.out.println("磁盘扫描序列为:");
	System.out.print( now);
    for( i=0;i<m;i++)   //输出磁盘扫描序列
    {
		System.out.print( " --> " + cidao[i]);
    }
    for(i=0;i<m-1;i++)   //求平均寻道长度 
    {
        sum+=Math.abs(cidao[i+1]-cidao[i]);
        ave=(float)sum/m;
    }
	System.out.println();
	System.out.println("平均寻道长度:"+ave);
}

2.5.2 SSTF关键代码

/**有三种情况:前提是先按升序排序好
	 * 1、若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
	 * 2、若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务,与第一种同理
	 * 3、若当前磁道号大于请求序列中最小者且小于最大者
	 * 最短寻到时间优先算法
	 * @param cidao 要访问的磁道数组
	 * @param m
	 */
void SSTF(int cidao[],int m)
{
   int k=1;                   //用于第三种情况找到当前磁道号在排序好序列的位置
   int now = -1,left = -1,right = -1;
   int i,j,sum=0;
 
   float ave = 0.0f;     //用来存平均寻道长度
   Arrays.sort(cidao); //调用快速排序算法升序处理
   System.out.println("排序后:"); 
   for (int n = 0; n < cidao.length; n++) {
	System.out.print(cidao[n] + "  ");
}
   System.out.println();
   System.out.print("请输入当前的磁道号:");
	Scanner input =new Scanner(System.in);
	now = input.nextInt(); 
	                        //注:柱面的编号是从外到内从0开始编号的
   if(cidao[m-1]<=now)     // 第一种种情况:若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
   {                       //比如:排序后 55 66 72 88 93 100 若当前磁道大于100就直接从100开始予以各请求服务
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
      System.out.print(" --> " + cidao[i]);
      sum=now-cidao[0];  
   }
   
   if(cidao[0]>=now)      // 第二种情况:若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务,与第一种同理
   {                   
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=0;i<m;i++)
	  System.out.print( " --> " + cidao[i]);
      sum=cidao[m-1]-now;
   }
   
   if(now>cidao[0]&&now<cidao[m-1])   //第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
   {
	   System.out.println("磁盘扫描序列为:");
	   
       while(cidao[k]<now)        //确定当前磁道在已排的序列中的位置
	   {
          k++;                   //k从1开始找
                                 //例如:55 66 72 88 93 100 若当前磁道号为90 直到找到93才会跳出循环,此时k=4
	   }
       left=k-1;                   //表示此时位置的左边逻辑下标  
       right=k;                     //表示此时位置的右边逻辑下表
       
       
       System.out.print(now); 
       while((left>=0)&&(right<m))    //当前磁道在请求序列范围内
    	                      
	   {    
          if((now-cidao[left])<=(cidao[right]-now))       //选择与当前磁道最近的请求给予服务,
		  {                                     //例如90和88比较在和93比较看谁距离短就先给哪个服务
			 System.out.print( " --> " + cidao[left]); //这是左边距离近的情况
             sum+=now-cidao[left];
             now=cidao[left];
             left=left-1;
		  }
          else
		  {  //System.out.print(now);
			 System.out.print( " --> " + cidao[right]);  //这是右边距离近的情况
             sum+=cidao[right]-now;
             now=cidao[right];
             right=right+1;
		  }
	   }
       
       if(left==-1)   //磁头移动到序列的最小号,返回内侧扫描仍未扫描的磁道
	   {
          for(j=right;j<m;j++)
		  {
			 System.out.print( "--> "+ cidao[j]);
		  }
          sum+=cidao[m-1]-cidao[0];
	   }
       else      //磁头移动到序列的最大号,返回外侧扫描仍未扫描的磁道
	   {
          for(j=left;j>=0;j--)
		  {
			 System.out.print( "--> "+ cidao[j]);//例如55 66 72 88 93 100假设当前磁道90
		  }                                      //则按前面的算法会有90-->88-->93-->100,此时到100时right+1=6跳出循环
          sum+=cidao[m-1]-cidao[0];              //来到了else这个分支,把磁头转到之前left的位置循环输出
	   }                                         //那个sum直接等于最后一个减去第一个,因为他总是会扫描到最外侧的磁道号
   }                                             //和(100-72)+(72-66)+(66-55)= 100-55 = 45 是一样的
   
   ave=sum/(float)(m);
   System.out.println();
   System.out.println("平均寻道长度: "+ave);
}

2.5.3 SCAN关键代码

/**
 * 这个算法和最短寻道差不多一样的,先排序,也有三种情况,但是多了一个选择移动臂的方向
 * 1、若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
 * 2、若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务
 * 3、第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
 * 扫描算法(电梯算法)
 * @param cidao  用来存磁道号
 * @param m
 */
void SCAN(int cidao[],int m)    //先要给出当前磁道号和移动臂的移动方向
{
   int k=1;
   int now,left = -1,right = -1 ,choice = -1 ;
   int i,j,sum=0;
   float ave = 0.0f;
   Arrays.sort(cidao);
System.out.println("排序后:");
   
   for (int n = 0; n < cidao.length; n++) {
	System.out.print(cidao[n] + "  ");
}
   System.out.println();
    System.out.print("请输入当前的磁道号:");
	Scanner input =new Scanner(System.in);
	now = input.nextInt();
   if(cidao[m-1]<=now)    //第一种情况:若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
   {   
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
	  System.out.print( " --> " + cidao[i]);
      sum=now-cidao[0];   //反正都要扫描到最外侧,直接减最小的那个得的距离和一个一个减在相加是等价的
   }
   if(cidao[0]>=now)     //第二种情况:若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务
   {   
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=0;i<m;i++)
      System.out.print(" --> " + cidao[i]);
      sum=cidao[m-1]-now;        //同理
   }
   if(now>cidao[0]&&now<cidao[m-1])   //第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
   {
       while(cidao[k]<now) //和SSTF算法一样先找到当前寻道号的位置
	   {
           k++;
	   }
       left=k-1;
       right=k;
	   System.out.println("请输入当前移动臂的移动的方向 (1 表示向内 ,0表示向外) : ");
	   Scanner input2 = new Scanner(System.in);
	   choice=input2.nextInt();
       if(choice==0)     //选择移动臂方向向外,则先向外扫描
	   {
		   System.out.println("磁盘扫描序列为:");
		   System.out.print(now);
           for(j = left;j >= 0;j--)  //往磁道号小的方向扫描,即向外扫描
		   {
			  System.out.print( " --> "+ cidao[j]);
		   }
           for(j=right;j<m;j++)   //磁头移动到最小号,则改变方向向内扫描未扫描的磁道
		   {
			  System.out.print(" --> " + cidao[j]);
		   }
           sum=now-2*cidao[0]+cidao[m-1]; //还是拿55 66 72 88 93 100举例子,当前磁道号是90,那么90先会往内扫描,扫描到最小号
	   }                                //然后在转回到了right=93处,又再一次经过了now,然后向右扫描到最大号
                                       //所以可以这么算sum =(now-cidao[0])*2 + (cidao[m-1]-now)
       
       
       else     //选择移动臂方向向外,则先向外扫描
	   {
		   System.out.println("磁盘扫描序列为:");
		   System.out.print(now);
           for(j=right;j<m;j++)
		   {
			  System.out.print(" --> " + cidao[j]);
		   }
           for(j=left;j>=0;j--)    //磁头移动到最大号,则改变方向向外扫描未扫描的磁道
		   {
			  System.out.print(" --> " + cidao[j]);
		   }
           sum=-now-cidao[0]+2*cidao[m-1]; //同理sum =(cidao[m-1]-now)*2 + (now - cidao[0])
	   }
   }
   ave=sum/(float)(m);
   System.out.println();
   System.out.print("平均寻道长度: " + ave);
}

2.5.4 CSCAN关键代码


 /**这个也要先排序,这里是升序,循环扫描也有三种情况
  * 1、若当前磁道号大于请求序列中最大者,则直接将移动臂移动到最小号磁道依次向内给予各请求服务 
  * 2、若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务,就和SSTF一样了
  * 3、若当前磁道号大于请求序列中最小者且小于最大者
  * 循环扫描算法(即单向扫描,没有访问时磁头不动,若访问到最小号则直接跳到最大号往最小号单向扫描,反之一样。)
  * @param cidao //存的是磁道号
  * @param m
  */
void CSCAN(int cidao[],int m)        //我默认是扫描方向是先向磁道号变小的方向进行,即从内到外
{
   int k=1;
   int now = -1,left = -1,right = -1;
   int i,j,sum=0;
   float ave;
    Arrays.sort(cidao);
    System.out.println("排序后:");
    for (int n = 0; n < cidao.length; n++) {
 	System.out.print(cidao[n] + "  ");
 }
    System.out.println();
    System.out.print("请输入当前的磁道号:");
	Scanner input = new Scanner(System.in);
	now=input.nextInt();
   if(cidao[m-1]<=now)   //第一种情况:若当前磁道号大于请求序列中最大者,则直接将移动臂移动到最小号磁道依次向内给予各请求服务 
   {
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
      System.out.print( " --> " + cidao[i]);
      sum=now-cidao[0]; //和SCAN算法一样 55 66 72 88 93 100 当前磁道号为101
   }                    
   
   
   if(cidao[0]>=now) //第二种情况:若当前磁道号小于请求序列中最小者,则移动磁道到最大位置由外向内依次给予各请求服务,
   {
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
      System.out.print(" --> " + cidao[i]);
      sum=2*cidao[m-1]-now-cidao[0];   //55 66 72 88 93 100 当前磁道号54
   }                        //sum = (cidao[m-1] - now) + (cidao[m-1]-cidao[0])
   
   
   if(now>cidao[0]&&now<cidao[m-1])  //第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
   {
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      while(cidao[k]<now)    //同上,先找到当前磁道号的位置
	  {
          k++;
	  }
      left= k-1;
      right = k;
      for(j=left;j>=0;j--)          //因为是默认先扫描最小磁道号在移到最大磁道号扫描
	  {                             //例:55 66 72 88 93 100 当前磁道号90
		  System.out.print( " --> "+ cidao[j]);
	  }
      for(j=m-1;j>left;j--) //当扫描完最小号磁道,磁头直接移动到最大号磁道,再向外扫描未扫描的磁道
	  {
		  System.out.print( " --> " + cidao[j]);
	  }
      sum=2*cidao[m-1]-cidao[right]+now-2*cidao[0];//sum=(now-cidao[0])+(cidao[m-1]-cidao[0])+(cidao[m-1]-cidao[right])
   }
   ave=sum/(float)(m);
   System.out.println();
   System.out.println("平均寻道长度: " + ave );
}
 
}

2.5.5 完整代码

package DiskManage;
import java.util.Scanner;
import java.util.Arrays;
/**
 * 磁盘调度FCFS、SSTF、SCAN、CSCAN
 * @author Monster丶ZF
 * @version1.8
 * @data 2019年7月2日
 * @remakeTODO
 */

    public class DiskManage{
	public static void main(String[] args){
		/*
		要用到的几种算法分别是
		冒泡排序算法
		先来先服务调度算法
		最短寻道时间优先调度算法
		扫描调度算法
		循环扫描调度算法
		*/
		DiskManage A = new DiskManage();
		   
   int choice = -1; 
   int[] cidao={55,72,100,88,93,66}; //用来存磁道号
   //int[] cidao = new int[6];
   int i = -1;     //全局变量i
   int[] str=new int[6];
   
   System.out.println("随机产生一个磁道序列(包含6个磁道)\n");
   
//   for(i=0;i<6;i++){
//   		str[i]=(int)(Math.random()*100); //随机产生一个0-100的磁道号
//   		cidao[i]=str[i];
//   }
   
   System.out.println("随机得到的磁道序列为:");
   
   for(i=0;i<6;i++)    
   {
	  System.out.print(cidao[i]+"  ");
   }
   System.out.println();
   while(true)
   {
      System.out.println();
	  System.out.println("----------------------------------------------");
	  System.out.println("|                 增福系统菜单                                 |");
	  System.out.println("|                                            |");
	  System.out.println("|               1. 先来先服务                                   |");
	  System.out.println("|               2. 最短寻道时间优先                        |");
	  System.out.println("|               3. 扫描(电梯)调度                        |");
	  System.out.println("|               4. 循环扫描                                      |");
	  System.out.println("|               5. 退出增福菜单                               |");
	  System.out.println("----------------------------------------------");
	  System.out.print("请选择算法:");
	  Scanner input =new Scanner(System.in);
	  choice=input.nextInt();     
      if(choice==5){
      System.err.println("已成功退出增福程序!");
        break;
      }
      switch(choice)
	  {
         case 1:    //使用FCFS算法
         A.FCFS(cidao,6);
         break;
         case 2:    //使用SSTF算法
         A.SSTF(cidao,6);
         break;
         case 3:    //使用SCAN算法
         A.SCAN(cidao,6);
         break;
         case 4:    //使用CSCAN算法
         A.CSCAN(cidao,6);
         break;
         default: 
         System.err.println("请输入1-5之间的数字");
	  }
   }
	}
	
	/**
	 * 先来先服务算法
	 * @param cidao 要访问的磁道数组
	 * @param m
	 */
	void FCFS(int cidao[],int m)   //磁道号数组,个数为m 
{
    int now = -1;     //当前磁道号
    int sum = 0;	 //总寻道长度
    int i;
    float ave=0.0f;   //平均寻道长度
	System.out.println("磁盘请求序列为:");
    for( i=0;i<m;i++)   //按先来先服务的策略输出磁盘请求序列
    {
		System.out.print(cidao[i]+"  ");
    }
	System.out.println();
	System.out.print("请输入当前的磁道号:");
	Scanner input = new Scanner(System.in);
	  now=input.nextInt();
    sum+=Math.abs(cidao[0]-now);//求当前输入磁道和第一要访问磁道的距离
	System.out.println("磁盘扫描序列为:");
	System.out.print( now);
    for( i=0;i<m;i++)   //输出磁盘扫描序列
    {
		System.out.print( " --> " + cidao[i]);
    }
    for(i=0;i<m-1;i++)   //求平均寻道长度 
    {
        sum+=Math.abs(cidao[i+1]-cidao[i]);
        ave=(float)sum/m;
    }
	System.out.println();
	System.out.println("平均寻道长度:"+ave);
}
 
	
	
	/**有三种情况:前提是先按升序排序好
	 * 1、若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
	 * 2、若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务,与第一种同理
	 * 3、若当前磁道号大于请求序列中最小者且小于最大者
	 * 最短寻到时间优先算法
	 * @param cidao 要访问的磁道数组
	 * @param m
	 */
void SSTF(int cidao[],int m)
{
   int k=1;                   //用于第三种情况找到当前磁道号在排序好序列的位置
   int now = -1,left = -1,right = -1;
   int i,j,sum=0;
 
   float ave = 0.0f;     //用来存平均寻道长度
   Arrays.sort(cidao); //调用快速排序算法升序处理
   System.out.println("排序后:"); 
   for (int n = 0; n < cidao.length; n++) {
	System.out.print(cidao[n] + "  ");
}
   System.out.println();
   System.out.print("请输入当前的磁道号:");
	Scanner input =new Scanner(System.in);
	now = input.nextInt(); 
	                        //注:柱面的编号是从外到内从0开始编号的
   if(cidao[m-1]<=now)     // 第一种种情况:若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
   {                       //比如:排序后 55 66 72 88 93 100 若当前磁道大于100就直接从100开始予以各请求服务
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
      System.out.print(" --> " + cidao[i]);
      sum=now-cidao[0];  
   }
   
   if(cidao[0]>=now)      // 第二种情况:若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务,与第一种同理
   {                   
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=0;i<m;i++)
	  System.out.print( " --> " + cidao[i]);
      sum=cidao[m-1]-now;
   }
   
   if(now>cidao[0]&&now<cidao[m-1])   //第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
   {
	   System.out.println("磁盘扫描序列为:");
	   
       while(cidao[k]<now)        //确定当前磁道在已排的序列中的位置
	   {
          k++;                   //k从1开始找
                                 //例如:55 66 72 88 93 100 若当前磁道号为90 直到找到93才会跳出循环,此时k=4
	   }
       left=k-1;                   //表示此时位置的左边逻辑下标  
       right=k;                     //表示此时位置的右边逻辑下表
       
       
       System.out.print(now); 
       while((left>=0)&&(right<m))    //当前磁道在请求序列范围内
    	                      
	   {    
          if((now-cidao[left])<=(cidao[right]-now))       //选择与当前磁道最近的请求给予服务,
		  {                                     //例如90和88比较在和93比较看谁距离短就先给哪个服务
			 System.out.print( " --> " + cidao[left]); //这是左边距离近的情况
             sum+=now-cidao[left];
             now=cidao[left];
             left=left-1;
		  }
          else
		  {  //System.out.print(now);
			 System.out.print( " --> " + cidao[right]);  //这是右边距离近的情况
             sum+=cidao[right]-now;
             now=cidao[right];
             right=right+1;
		  }
	   }
       
       if(left==-1)   //磁头移动到序列的最小号,返回内侧扫描仍未扫描的磁道
	   {
          for(j=right;j<m;j++)
		  {
			 System.out.print( "--> "+ cidao[j]);
		  }
          sum+=cidao[m-1]-cidao[0];
	   }
       else      //磁头移动到序列的最大号,返回外侧扫描仍未扫描的磁道
	   {
          for(j=left;j>=0;j--)
		  {
			 System.out.print( "--> "+ cidao[j]);//例如55 66 72 88 93 100假设当前磁道90
		  }                                      //则按前面的算法会有90-->88-->93-->100,此时到100时right+1=6跳出循环
          sum+=cidao[m-1]-cidao[0];              //来到了else这个分支,把磁头转到之前left的位置循环输出
	   }                                         //那个sum直接等于最后一个减去第一个,因为他总是会扫描到最外侧的磁道号
   }                                             //和(100-72)+(72-66)+(66-55)= 100-55 = 45 是一样的
   
   ave=sum/(float)(m);
   System.out.println();
   System.out.println("平均寻道长度: "+ave);
}
 
/**
 * 这个算法和最短寻道差不多一样的,先排序,也有三种情况,但是多了一个选择移动臂的方向
 * 1、若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
 * 2、若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务
 * 3、第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
 * 扫描算法(电梯算法)
 * @param cidao  用来存磁道号
 * @param m
 */
void SCAN(int cidao[],int m)    //先要给出当前磁道号和移动臂的移动方向
{
   int k=1;
   int now,left = -1,right = -1 ,choice = -1 ;
   int i,j,sum=0;
   float ave = 0.0f;
   Arrays.sort(cidao);
System.out.println("排序后:");
   
   for (int n = 0; n < cidao.length; n++) {
	System.out.print(cidao[n] + "  ");
}
   System.out.println();
    System.out.print("请输入当前的磁道号:");
	Scanner input =new Scanner(System.in);
	now = input.nextInt();
   if(cidao[m-1]<=now)    //第一种情况:若当前磁道号大于请求序列中最大者,则直接由内向外依次给予各请求服务
   {   
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
	  System.out.print( " --> " + cidao[i]);
      sum=now-cidao[0];   //反正都要扫描到最外侧,直接减最小的那个得的距离和一个一个减在相加是等价的
   }
   if(cidao[0]>=now)     //第二种情况:若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务
   {   
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=0;i<m;i++)
      System.out.print(" --> " + cidao[i]);
      sum=cidao[m-1]-now;        //同理
   }
   if(now>cidao[0]&&now<cidao[m-1])   //第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
   {
       while(cidao[k]<now) //和SSTF算法一样先找到当前寻道号的位置
	   {
           k++;
	   }
       left=k-1;
       right=k;
	   System.out.println("请输入当前移动臂的移动的方向 (1 表示向内 ,0表示向外) : ");
	   Scanner input2 = new Scanner(System.in);
	   choice=input2.nextInt();
       if(choice==0)     //选择移动臂方向向外,则先向外扫描
	   {
		   System.out.println("磁盘扫描序列为:");
		   System.out.print(now);
           for(j = left;j >= 0;j--)  //往磁道号小的方向扫描,即向外扫描
		   {
			  System.out.print( " --> "+ cidao[j]);
		   }
           for(j=right;j<m;j++)   //磁头移动到最小号,则改变方向向内扫描未扫描的磁道
		   {
			  System.out.print(" --> " + cidao[j]);
		   }
           sum=now-2*cidao[0]+cidao[m-1]; //还是拿55 66 72 88 93 100举例子,当前磁道号是90,那么90先会往内扫描,扫描到最小号
	   }                                //然后在转回到了right=93处,又再一次经过了now,然后向右扫描到最大号
                                       //所以可以这么算sum =(now-cidao[0])*2 + (cidao[m-1]-now)
       
       
       else     //选择移动臂方向向外,则先向外扫描
	   {
		   System.out.println("磁盘扫描序列为:");
		   System.out.print(now);
           for(j=right;j<m;j++)
		   {
			  System.out.print(" --> " + cidao[j]);
		   }
           for(j=left;j>=0;j--)    //磁头移动到最大号,则改变方向向外扫描未扫描的磁道
		   {
			  System.out.print(" --> " + cidao[j]);
		   }
           sum=-now-cidao[0]+2*cidao[m-1]; //同理sum =(cidao[m-1]-now)*2 + (now - cidao[0])
	   }
   }
   ave=sum/(float)(m);
   System.out.println();
   System.out.print("平均寻道长度: " + ave);
}
 


 /**这个也要先排序,这里是升序,循环扫描也有三种情况
  * 1、若当前磁道号大于请求序列中最大者,则直接将移动臂移动到最小号磁道依次向内给予各请求服务 
  * 2、若当前磁道号小于请求序列中最小者,则直接由外向内依次给予各请求服务,就和SSTF一样了
  * 3、若当前磁道号大于请求序列中最小者且小于最大者
  * 循环扫描算法(即单向扫描,没有访问时磁头不动,若访问到最小号则直接跳到最大号往最小号单向扫描,反之一样。)
  * @param cidao //存的是磁道号
  * @param m
  */
void CSCAN(int cidao[],int m)        //我默认是扫描方向是先向磁道号变小的方向进行,即从内到外
{
   int k=1;
   int now = -1,left = -1,right = -1;
   int i,j,sum=0;
   float ave;
    Arrays.sort(cidao);
    System.out.println("排序后:");
    for (int n = 0; n < cidao.length; n++) {
 	System.out.print(cidao[n] + "  ");
 }
    System.out.println();
    System.out.print("请输入当前的磁道号:");
	Scanner input = new Scanner(System.in);
	now=input.nextInt();
   if(cidao[m-1]<=now)   //第一种情况:若当前磁道号大于请求序列中最大者,则直接将移动臂移动到最小号磁道依次向内给予各请求服务 
   {
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
      System.out.print( " --> " + cidao[i]);
      sum=now-cidao[0]; //和SCAN算法一样 55 66 72 88 93 100 当前磁道号为101
   }                    
   
   
   if(cidao[0]>=now) //第二种情况:若当前磁道号小于请求序列中最小者,则移动磁道到最大位置由外向内依次给予各请求服务,
   {
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      for(i=m-1;i>=0;i--)
      System.out.print(" --> " + cidao[i]);
      sum=2*cidao[m-1]-now-cidao[0];   //55 66 72 88 93 100 当前磁道号54
   }                        //sum = (cidao[m-1] - now) + (cidao[m-1]-cidao[0])
   
   
   if(now>cidao[0]&&now<cidao[m-1])  //第三种情况:若当前磁道号大于请求序列中最小者且小于最大者
   {
	  System.out.println("磁盘扫描序列为:");
	  System.out.print(now);
      while(cidao[k]<now)    //同上,先找到当前磁道号的位置
	  {
          k++;
	  }
      left= k-1;
      right = k;
      for(j=left;j>=0;j--)          //因为是默认先扫描最小磁道号在移到最大磁道号扫描
	  {                             //例:55 66 72 88 93 100 当前磁道号90
		  System.out.print( " --> "+ cidao[j]);
	  }
      for(j=m-1;j>left;j--) //当扫描完最小号磁道,磁头直接移动到最大号磁道,再向外扫描未扫描的磁道
	  {
		  System.out.print( " --> " + cidao[j]);
	  }
      sum=2*cidao[m-1]-cidao[right]+now-2*cidao[0];//sum=(now-cidao[0])+(cidao[m-1]-cidao[0])+(cidao[m-1]-cidao[right])
   }
   ave=sum/(float)(m);
   System.out.println();
   System.out.println("平均寻道长度: " + ave );
}
 
}

4运行结果及分析
4.1运行结果

SSTF结果图2-1在这里插入图片描述
SCAN结果图2-2
在这里插入图片描述
CSCAN结果图2-3在这里插入图片描述
随机产生磁道号SSTF结果图2-4加粗样式在这里插入图片描述
在这里插入图片描述
3.运行分析
(1)上面前三个结果是课本上的6个数据,因为FCFS比较简单,就不拿出来截图了,首先运行会弹出一个菜单,让你选择相应的调度算法,选择其中一个即可,也可以一直选择直到选择5退出,经过和课本比对和验算,磁道访问顺序和平均寻道时间都是正确的。

(2)图2-4是随机数产生的磁道号,我选择了第2算法示例,他会先排好序,然后开始算法,经过验算也是正确的,包括其他算法自己也私下验证了,都是正确的具有通用性。同时我还添加了一些提示,如果用户不小心输入的数字不是1-5就会弹出提示,然后让用户重新输入1-5之间的数字,如果没有要计算的就选择5退出程序即可。

  • 8
    点赞
  • 2
    评论
  • 47
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:马嘣嘣 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值