1. 程式人生 > >Java 模擬磁碟排程管理

Java 模擬磁碟排程管理

老師佈置的實習題目如下:設計目的:

加深對請求磁碟排程管理實現原理的理解,掌握磁碟排程演算法。

設計內容:

通過程式設計實現不同磁碟排程演算法。

設定開始磁軌號尋道範圍,依據起始掃描磁軌號和最大磁軌號數,隨機產生要進行尋道的磁軌號序列。選擇磁碟排程演算法,顯示該演算法的磁軌訪問順序,計算出移動的磁軌總數和平均尋道總數。

常用的磁碟排程演算法簡介如下,請在以下演算法中任意選擇兩種實現,並對演算法效能進行分析對比。

1. 最短尋道優先演算法SSTF:該演算法選擇這樣的程序:其要求訪問的磁軌與當前磁頭所在的磁軌距離最近,以使每次的尋道時間最短。

2. 掃描演算法SCAN:該演算法不僅考慮到欲訪問的磁軌與當前磁軌間的距離,更優先考慮的是磁頭當前的移動方向。例如,當磁頭正在自裡向外移動時,SCAN演算法所考慮的下一個訪問物件,應是其欲訪問的磁軌既在當前磁軌之外,又是距離最近的。這樣自裡向外地訪問,直至再無更外的磁軌需要訪問時,才將磁臂換向為自外向裡移動。

3.迴圈掃描演算法CSCAN:CSCAN演算法規定磁頭單向移動,例如,只是自裡向外移動,當磁頭移到最外的磁軌並訪問後,磁頭立即返回到最裡的欲訪問的磁軌,亦即將最小磁軌號緊接著最大磁軌號構成迴圈,進行迴圈掃描。程式碼如下:
import java.util.Scanner;
import java.util.Arrays;


class Cipandiaodu{
	public static void main(String[] args){
		/*
		要用到的幾種演算法分別是
		氣泡排序演算法
		先來先服務排程演算法
		最短尋道時間優先排程演算法
		掃描排程演算法
		迴圈掃描排程演算法
		*/
		Cipandiaodu A=new Cipandiaodu();
   int a;
   int now;   
   int c; 
   int[] cidao=new int[1000];
   int i=0,count; 
   int[] str=new int[100];
   System.out.println("隨機產生一個磁軌序列(包含10個磁軌)\n");
   for(i=0;i<10;i++){
   		str[i]=(int)(Math.random()*200);
   		cidao[i]=str[i];
   }
   count=i-1;     
   System.out.println("得到的磁軌序列為:");
   for(i=0;i<count;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.print("請選擇演算法:");
	  Scanner w=new Scanner(System.in);
	  c=w.nextInt();     
      if(c==5)
        break;
      switch(c)
	  {
         case 1:    //使用FCFS演算法
         A.FCFS(cidao,count);
         break;
         case 2:    //使用SSTF演算法
         A.SSTF(cidao,count);
         break;
         case 3:    //使用SCAN演算法
         A.SCAN(cidao,count);
         break;
         case 4:    //使用CSCAN演算法
         A.CSCAN(cidao,count);
         break;
	  }
   }
	}
	
	void FCFS(int cidao[],int m)   //磁軌號陣列,個數為m 
{
    int now;//當前磁軌號
    int sum=0;	//總尋道長度
    int j,i;
	int a;
    float ave=0;   //平均尋道長度
	System.out.println("磁碟請求序列為:");
    for( i=0;i<m;i++)   //按先來先服務的策略輸出磁碟請求序列
    {
		System.out.print(cidao[i]+" ");
    }
	System.out.println();
	System.out.print("請輸入當前的磁軌號:");
	Scanner w=new Scanner(System.in);
	  now=w.nextInt();
    sum+=Math.abs(cidao[0]-now);
	System.out.println("磁碟掃描序列為:");
    for( i=0;i<m;i++)   //輸出磁碟掃描序列
    {
		System.out.print(cidao[i]+" ");
    }
    for(i=0,j=1;j<m;i++,j++)   //求平均尋道長度
    {
        sum+=Math.abs(cidao[j]-cidao[i]);
        ave=(float)sum/m;
    }
	System.out.println();
	System.out.println("平均尋道長度:"+ave);
}

void SSTF(int cidao[],int m)
{
   int k=1;
   int now,l,r;
   int i,j,sum=0;
   int a;

   float ave;
   Arrays.sort(cidao);
 	System.out.print("請輸入當前的磁軌號:");
	Scanner w=new Scanner(System.in);
	now=w.nextInt();
   if(cidao[m-1]<=now)   //若當前磁軌號大於請求序列中最大者,則直接由外向內依次給予各請求服務
   {
	  System.out.println("磁碟掃描序列為:");
      for(i=m-1;i>=0;i--)
      System.out.print(cidao[i]+" ");
      sum=now-cidao[0];
   }
   if(cidao[0]>=now)   //若當前磁軌號小於請求序列中最小者,則直接由內向外依次給予各請求服務
   {
	  System.out.println("磁碟掃描序列為:");
      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++;
	   }
       l=k-1;
       r=k;
       while((l>=0)&&(r<m))   //當前磁軌在請求序列範圍內
	   {
          if((now-cidao[l])<=(cidao[r]-now))   //選擇與當前磁軌最近的請求給予服務
		  {
			 System.out.print(cidao[l]+" ");
             sum+=now-cidao[l];
             now=cidao[l];
             l=l-1;
		  }
          else
		  {
			 System.out.print(cidao[r]+" ");
             sum+=cidao[r]-now;
             now=cidao[r];
             r=r+1;
		  }
	   }
       if(l==-1)   //磁頭移動到序列的最小號,返回外側掃描仍未掃描的磁軌
	   {
          for(j=r;j<m;j++)
		  {
			 System.out.print(cidao[j]+" ");
		  }
          sum+=cidao[m-1]-cidao[0];
	   }
       else    //磁頭移動到序列的最大號,返回內側掃描仍未掃描的磁軌
	   {
          for(j=l;j>=0;j--)
		  {
			 System.out.print(cidao[j]+" ");
		  }
          sum+=cidao[m-1]-cidao[0];
	   }
   }
   ave=(float)(sum)/(float)(m);
   System.out.println();
   System.out.println("平均尋道長度: "+ave);
}

void SCAN(int cidao[],int m)    //先要給出當前磁軌號和移動臂的移動方向
{
   int k=1;
   int now,l,r,d;
   int i,j,sum=0;
   int a;
   float ave;
   Arrays.sort(cidao);
    System.out.print("請輸入當前的磁軌號:");
	Scanner w=new Scanner(System.in);
	now=w.nextInt();
   if(cidao[m-1]<=now)    //若當前磁軌號大於請求序列中最大者,則直接由外向內依次給予各請求服務,此情況同最短尋道優先
   {   
	  System.out.println("磁碟掃描序列為:");
      for(i=m-1;i>=0;i--)
	  System.out.print(cidao[i]+" ");
      sum=now-cidao[0];
   }
   if(cidao[0]>=now)     //若當前磁軌號小於請求序列中最小者,則直接由內向外依次給予各請求服務,此情況同最短尋道優先
   {   
	  System.out.println("磁碟掃描序列為:");
      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)
	   {
           k++;
	   }
       l=k-1;
       r=k;
	   System.out.println("請輸入當前移動臂的移動的方向 (1 表示向外 ,0表示向內) : ");
	   Scanner x=new Scanner(System.in);
	   d=x.nextInt();
       if(d==0)     //選擇移動臂方向向內,則先向內掃描
	   {
		   System.out.println("磁碟掃描序列為:");
           for(j=l;j>=0;j--)
		   {
			  System.out.print(cidao[j]+" ");
		   }
           for(j=r;j<m;j++)   //磁頭移動到最小號,則改變方向向外掃描未掃描的磁軌
		   {
			  System.out.print(cidao[j]+" ");
		   }
           sum=now-2*cidao[0]+cidao[m-1];
	   }
       else     //選擇移動臂方向向外,則先向外掃描
	   {
		   System.out.println("磁碟掃描序列為:");
           for(j=r;j<m;j++)
		   {
			  System.out.print(cidao[j]+" ");
		   }
           for(j=l;j>=0;j--)    //磁頭移動到最大號,則改變方向向內掃描未掃描的磁軌
		   {
			  System.out.print(cidao[j]+" ");
		   }
           sum=-now-cidao[0]+2*cidao[m-1];
	   }
   }	 
   ave=(float)(sum)/(float)(m);
   System.out.println();
   System.out.print("平均尋道長度: ");
}


void CSCAN(int cidao[],int m)
{
   int k=1;
   int now,l,r;
   int i,j,sum=0;
   int a;
   float ave;
    Arrays.sort(cidao);
    System.out.print("請輸入當前的磁軌號:");
	Scanner w=new Scanner(System.in);
	now=w.nextInt();
   if(cidao[m-1]<=now)   //若當前磁軌號大於請求序列中最大者,則直接將移動臂移動到最小號磁軌依次向外給予各請求服務 
   {
	  System.out.println("磁碟掃描序列為:");
      for(i=0;i<m;i++)
      System.out.print(cidao[i]+" ");
      sum=now-2*cidao[0]+cidao[m-1];
   }
   if(cidao[0]>=now) //若當前磁軌號小於請求序列中最小者,則直接由內向外依次給予各請求服務,此情況同最短尋道優先
   {
	  System.out.println("磁碟掃描序列為:");
      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++;
	  }
      l=k-1;
      r=k;
      for(j=r;j<m;j++)
	  {
		  System.out.print(cidao[j]+" ");
	  }
      for(j=0;j<r;j++)     //當掃描完最大號磁軌,磁頭直接移動到最小號磁軌,再向外掃描未掃描的磁軌
	  {
		  System.out.print(cidao[j]+" ");
	  }
      sum=2*cidao[m-1]+cidao[l]-now-2*cidao[0];
   }
   ave=(float)(sum)/(float)(m);
   System.out.println();
   System.out.println("平均尋道長度: ");
}

}

如有不對,歡迎指出。