1. 程式人生 > >用JAVASwing實現模擬磁碟排程

用JAVASwing實現模擬磁碟排程

通過使用JavaSwing 可以很方便地創建出圖形介面,那麼在通過java演算法解決某些問題的時候可以結合圖形介面程式設計,就可以非常直觀地表達你的意圖。以下將說明一個實現模擬磁碟排程的的例子。準備好上車了嗎?Let’s go!

 首先我們要明確的是磁碟排程主要要用到哪些排程演算法,有先來先服務演算法,最短尋道優先演算法,掃描(電梯排程)演算法等。然後設計一個類,提供這些演算法對應的方法。

1.Arithmetic.java

import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Arithmetic
extends JPanel{
LogPane log; public Arithmetic(){ log=LogPane.getLog(); } /*判斷輸入資料是否有效*/ public int decide(char str[]) { int i=0; while(str[i]!=0){ if(str[i]<'0'||str[i]>'9'){ return 0; //break; } i++; } return i; } /*將字串轉換為數字*/ int trans(char str[],int a){ int i; int sum=0; for
(i=0;i<a;i++){ sum=sum+(int)((str[i]-'0')*Math.pow(10,a-i-1)); } return sum; } /*氣泡排序演算法*/ int []bubble(int cidao[],int m){ int i,j; int temp; for(i=0;i<m;i++)//使用冒泡法從小到大順序排列 for(j=i+1;j<m;j++){ if(cidao[i]>cidao[j]){ temp=cidao[i]; cidao[i]=cidao[j]; cidao[j]=temp; } } return
cidao; } /*先來先服務演算法*/ public void FCFS(int cidao[],int now) //磁軌號陣列,個數為M { //int now;//當前磁軌號 int sum=0;//總尋道長度 int i,j; int count=0; int len=0; float ave = 0;//平均尋道長度 sum+=Math.abs(cidao[0]-now); count=count+1; System.out.println(sum); //cout<<"磁碟掃描序列為: "; String buffer=""; for(i=0;i<cidao.length;i++) {//輸出磁碟掃描序列 // cout<<cidao[i]<<" "; if(cidao[i]>0){ len++; buffer+=cidao[i]+" "; } } log.addLog("磁碟掃描序列為: "+buffer.toString()); for(i=0,j=1;j<len;i++,j++){ sum+=Math.abs(cidao[j]-cidao[i]); count++; } ave= sum/len; System.out.println("sum="+sum+" count="+count); //cout<<endl; //cout<<"平均尋道長度: "<<ave<<endl; log.addLog("平均尋道長度:"+ave); } /*最短尋道時間優先排程演算法*/ public void SSTF(int cidao[],int now){ int k=1; int l,r,len=0; int i,j,sum=0; int a,count=0; float ave; for(i=0;i<cidao.length;i++) { // cout<<cidao[i]<<" "; if(cidao[i]>0){ len++; } } cidao=bubble(cidao,len); //呼叫氣泡排序演算法排序 String s=""; for(int z=0;z<len;z++){ // System.out.println(cidao[z]); s+=cidao[z]+" "; } log.addLog("磁軌序列從小到大排序為:"+s); if(cidao[len-1]<=now) //若當前磁軌號大於請求序列中最大者,則直接由外向內依次給予各請求服務 { String buffer=""; // cout<<"磁碟掃描序列為: "; for(i=len-1;i>=0;i--){ buffer+=cidao[i]+" "; } log.addLog("磁碟掃描序列為: "+buffer.toString()); sum=now-cidao[0]; count=len; } if(cidao[0]>=now){ //若當前磁軌號小於請求序列中最小者,則直接由內向外依次給予各請求服務; String buffer=""; for(i=0;i<len;i++){ buffer+=cidao[i]+" "; } log.addLog("磁碟掃描序列為: "+buffer.toString()); sum=cidao[len-1]-now; count=len; } if(now>cidao[0]&&now<cidao[len-1]) {//若當前磁軌號大於當前請求序列中最小者並且小於最大者 // cout<<"磁碟掃描序列為: "; StringBuffer buffer=new StringBuffer(""); while(cidao[k]<now){ //確定當前磁軌在已排的序列中的位置 k++; } l=k-1; r=k; while((l>=0)&&(r<len)){ //當前磁軌在請求序列範圍內 if(now-cidao[l]<=(cidao[r]-now)) {//選擇與當前磁軌最近的請求給予服務 // cout<<cidao[l]<<" "; buffer.append(cidao[l]+" "); sum+=now-cidao[l]; now=cidao[l]; l=l-1; } else{ // cout<<cidao[r]<<" "; buffer.append(cidao[r]+" "); sum+=cidao[r]-now; now=cidao[r]; r=r+1; } } if(l==-1) {//磁頭移動到序列的最小號,返回外側掃描仍未掃描的磁軌 for(j=r;j<len;j++){ // cout<<cidao[j]<<" "; buffer.append(cidao[j]+" "); } sum+=cidao[len-1]-cidao[0]; } else{ //磁頭移動到序列的最大號,返回內側掃描仍未掃描的磁軌 for(j=l;j>=0;j--){ // cout<<cidao[j]<<" "; buffer.append(cidao[j]+" "); } sum+=cidao[len-1]-cidao[0]; } log.addLog("磁碟掃描序列為: "+buffer.toString()); } ave=sum/len; log.addLog("平均尋道長度:"+ave); // cout<<endl; // cout<<"平均尋道長度: "<<ave<<endl; } /*掃描排程演算法*/ public void SCAN(int cidao[],int now) { //先要給出當前磁軌號和移動臂的移動方向 int k=1; int l,r,d=0; int i,j,sum=0; int a,len=0; char str[ ]=new char[100]; float ave; for(i=0;i<cidao.length;i++) { // cout<<cidao[i]<<" "; if(cidao[i]>0){ len++; } } cidao=bubble(cidao,len);//呼叫氣泡排序演算法排序 //cout<<"請輸入當前的磁軌號:"; String s=""; for(int z=0;z<len;z++){ // System.out.println(cidao[z]); s+=cidao[z]+" "; } log.addLog("磁軌序列從小到大排序為:"+s); if(cidao[len-1]<=now) //若當前磁軌號大於請求序列中最大者,則直接由外向內 //依次給予各請求服務,此情況同最短尋道優先 { // cout<<"磁碟掃描序列為:";//輸入當前磁軌號 StringBuffer buffer=new StringBuffer(""); for(i=len-1;i>=0;i--){ // cout<<cidao[i]<<" "; buffer.append(cidao[i]+" "); } log.addLog("磁碟掃描序列為: "+buffer.toString()); sum=now-cidao[0]; } if(cidao[0]>=now) //若當前磁軌號小於請求序列中最小者,則直接由內向外 //依次給予各請求服務,此情況同最短尋道優先 { StringBuffer buffer=new StringBuffer(""); // cout<<"磁碟掃描序列為: "; for(i=0;i<len;i++){ // cout<<cidao[i]<<" "; buffer.append(cidao[i]+" "); } log.addLog("磁碟掃描序列為: "+buffer.toString()); sum=cidao[len-1]-now; } if(now>cidao[0]&&now<cidao[len-1]) //若當前磁軌號大於請求序列中最小者且 //小於最大者 { StringBuffer buffer=new StringBuffer(""); while(cidao[k]<now){ k++; } l=k-1; r=k; try{ String string=JOptionPane.showInputDialog(this, "請輸入當前移動臂的移動的方向(1 表示向外,0表示向內):", "提示", JOptionPane.INFORMATION_MESSAGE); d=Integer.parseInt(string); //cout<<"請輸入當前移動臂的移動的方向(1 表示向外,0表示向內):"; //cin>>d; if(d==0) //選擇移動臂方向向內,則先向內掃描 { // cout<<"磁碟掃描序列為:"; for(j=1;j>=0;j--){ // cout<<cidao[j]<<" "; //輸出向內掃描的序列 buffer.append(cidao[j]+" "); } for(j=r;j<len;j++){ //磁頭移動到最小號,則改變方向向內掃描為掃描的磁軌 //cout<<cidao[j]<<" "; //輸出向外掃描的序列 buffer.append(cidao[j]+" "); } sum=now-2*cidao[0]+cidao[len-1]; } else{ //選擇移動臂方向向外,則先向外掃描 // cout<<"磁碟掃描序列為:"; for(j=r;j<len;j++){ // cout<<cidao[j]<<" ";//輸出向外掃描的序列 buffer.append(cidao[j]+" "); } for(j=l;j>=0;j--){ // cout<<cidao[j]<<" "; buffer.append(cidao[j]+" "); } sum=now-cidao[0]+2*cidao[len-1]; } log.addLog("磁碟掃描序列為: "+buffer.toString()); //cout<<endl; //cout<<"平均尋道長度: "<<ave<<endl; }catch(Exception e){ log.addLog(e.toString()); e.printStackTrace(); } } ave= sum/len; log.addLog("平均尋道長度:"+ave); } }
 其次,設計介面中要用到的面板類,有兩個,一個是選擇磁碟排程演算法的面板類ArithPane.java,一個是用來列印結果資訊的面板類LogPane.java

2.ArithPane.java

 import java.awt.*;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
public class ArithPane extends JPanel implements ActionListener{
JButton button1,button2,button3,backButton;
Font font=new Font("微軟雅黑",Font.PLAIN,16);
JLabel label;
LogPane log;
Arithmetic arith;
//int tem[]=new int[1000];
int now=0;
    public ArithPane() {
        // TODO 自動生成的建構函式存根
        //tem=DiskOperation.getCidao();
        init();      
    }
    public void init(){
        try { 
               UIManager
                 .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
              } catch (Exception e) {
               e.printStackTrace();
              }
        this.setLayout(null);
        this.setBorder(new TitledBorder("模擬磁碟排程介面"));
        log=LogPane.getLog();
        arith=new Arithmetic();
        label=new JLabel("請選擇以下演算法來模擬磁碟排程:");
        Font font1=new Font("微軟雅黑",Font.BOLD,16);
        label.setFont(font1);
        label.setBounds(20, 20, 350, 30);

        backButton=new JButton("返回");
        backButton.setFont(font);
        backButton.setBounds(530, 15, 80, 30);
        backButton.addActionListener(this);

        button1=new JButton("先來先服務演算法");
        button1.setFont(font);
        button1.setBounds(170, 80, 250, 30);
        button1.addActionListener(this);

        button2=new JButton("最短尋道優先演算法");
        button2.setFont(font);
        button2.setBounds(170, 150, 250, 30);
        button2.addActionListener(this);

        button3=new JButton("掃描(電梯排程)演算法");
        button3.setFont(font);
        button3.setBounds(170, 220, 250, 30);
        button3.addActionListener(this);

        this.add(backButton);
        this.add(label);
        this.add(button1);
        this.add(button2);
        this.add(button3);
        this.setVisible(true);

        }
    @Override
    public void actionPerformed(ActionEvent e) {
        int[] cidao=DiskOperation.getCidao();
        // TODO 自動生成的方法存根
        if(e.getSource()==backButton){
            DiskOperation.showCard();
            log.addLog("返回到主介面!");
        }

       if(e.getSource()==button1){
             int []tem = new int[cidao.length];
            for(int i=0;i<tem.length;i++){
                tem[i]=cidao[i];
            }
            int len=JOptionPane.showConfirmDialog(this, "你選擇的是先來先服務演算法", 
                    "提示", JOptionPane.YES_NO_OPTION);
            if(len==JOptionPane.OK_OPTION){
                try{
                String str=JOptionPane.showInputDialog(this, "請輸入當前磁軌號", 
                        "提示", JOptionPane.INFORMATION_MESSAGE);

                now=Integer.parseInt(str);
                log.addLog("正在模擬先來先服務演算法...");
            //  log.addLog("請求磁軌序列為:"+cidao);
                log.addLog("當前磁軌號為:"+now);
                arith.FCFS(tem,now);

                }catch(Exception e1){
                    e1.printStackTrace();
                    JOptionPane.showMessageDialog(this, "輸入型別錯誤!", "提示", 
                            JOptionPane.WARNING_MESSAGE);
                    log.addLog(e1.toString());
                }

            } 


            }
       if(e.getSource()==button2){
           int []tem = new int[cidao.length];
           for(int i=0;i<tem.length;i++){
                tem[i]=cidao[i];
            }
           int len=JOptionPane.showConfirmDialog(this, "你選擇的是最短尋道優先演算法", 
                    "提示", JOptionPane.YES_NO_OPTION);
            if(len==JOptionPane.OK_OPTION){
                try{
                String str=JOptionPane.showInputDialog(this, "請輸入當前磁軌號", 
                        "提示", JOptionPane.INFORMATION_MESSAGE);

                now=Integer.parseInt(str);
                log.addLog("正在模擬最短尋道優先演算法...");
            //  log.addLog("請求磁軌序列為:"+cidao);
                log.addLog("當前磁軌號為:"+now);
                arith.SSTF(tem,now);

                }catch(Exception e1){
                    e1.printStackTrace();
                    JOptionPane.showMessageDialog(this, "輸入型別錯誤!", "提示", 
                            JOptionPane.WARNING_MESSAGE);
                    log.addLog(e1.toString());
                }

            } 

       }
       if(e.getSource()==button3){
           int []tem = new int[cidao.length];
           for(int i=0;i<tem.length;i++){
                tem[i]=cidao[i];
            }
           int len=JOptionPane.showConfirmDialog(this, "你選擇的是掃描(電梯排程)演算法", 
                    "提示", JOptionPane.YES_NO_OPTION);
            if(len==JOptionPane.OK_OPTION){
                try{
                String str=JOptionPane.showInputDialog(this, "請輸入當前磁軌號", 
                        "提示", JOptionPane.INFORMATION_MESSAGE);

                now=Integer.parseInt(str);
                log.addLog("正在模擬掃描(電梯排程)演算法...");
            //  log.addLog("請求磁軌序列為:"+cidao);
                log.addLog("當前磁軌號為:"+now);
                arith.SCAN(tem, now);

                }catch(Exception e1){
                    e1.printStackTrace();
                    JOptionPane.showMessageDialog(this, "輸入型別錯誤!", "提示", 
                            JOptionPane.WARNING_MESSAGE);
                    log.addLog(e1.toString());
                }

            }   

       }

    }

}

3.LogPane.java(關於這個LogPane,它的好處是可以用來列印一些有用的資訊,在本人關於Java的其它文章中也有用到)

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Date;
public class LogPane extends JTabbedPane implements ActionListener{
private JScrollPane scroll;
private JTextArea textArea;
static final LogPane log=new LogPane();
    public LogPane() {
        // TODO 自動生成的建構函式存根
        try {  
               UIManager
                 .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
              } catch (Exception e) {
               e.printStackTrace();
              }

        textArea=new JTextArea();
        textArea.setLineWrap(true);
        textArea.setFont(new Font("TimesRoman",Font.PLAIN,18));
        scroll=new JScrollPane(textArea);
        add(scroll,BorderLayout.CENTER);
        this.setTitleAt(0, "Log");
        //this.setTitleAt(1, "sddsf");
        //this.setFont(new Font("TimesRoman",Font.BOLD,16));
        this.setFont(new Font("微軟雅黑",Font.BOLD,16));
        this.setEnabled(false);
        textArea.setEditable(false);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO 自動生成的方法存根

    }

    public void addLog(String log){
        Date current = new  Date(System.currentTimeMillis());
        textArea.append(log+"    "+current+"\n");
    }

    public static LogPane getLog(){

        return log;
    }

    public void addLog(String str,Color color){
        Date date=new Date();
        textArea.setForeground(color);
        textArea.append(str+"\t"+date+"\n");
    }
}
 最後,編寫主類DiskOperation.java,呼叫上面的兩個面板類和一個演算法類

4.DiskOperation.java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class DiskOperation extends JFrame implements ActionListener
{
ImageIcon img;
JSplitPane vsplitPane;
JSplitPane hsplitPane;
LogPane log;
JButton sureButton;
JPanel centerPane;
JPanel southPane;
JPanel pane;
static JPanel controlPane;
static CardLayout card;
Font font=new Font("微軟雅黑",Font.PLAIN,16);
JLabel label;
JTextField textField;
ArithPane arithPane;
static  int cidao[];
public DiskOperation( )
{

 try { 
       UIManager
         .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
      } catch (Exception e) {
       e.printStackTrace();
      } 

try {
    init();
} catch (Exception e) {
    // TODO 自動生成的 catch 塊
    log.addLog(e.toString());
}
}


private void setBorder(TitledBorder titledBorder) {
    // TODO Auto-generated method stub

}


public void init() throws Exception{
arithPane=new ArithPane();  
card=new CardLayout();
controlPane=new JPanel();
controlPane.setLayout(card);
controlPane.add("面板二", arithPane);
cidao=new int[1000];

textField=new JTextField();
textField.setFont(font);
textField.setBounds(150, 140, 300, 30);

label=new JLabel("請輸入要請求服務的磁軌序列(以空格隔開)");
label.setFont(font);
label.setBounds(140, 60, 350, 30);

log=LogPane.getLog();
log.addLog("歡迎來到模擬磁碟排程介面!");

pane=new JPanel();
pane.setLayout(new BorderLayout());

controlPane.add("面板一", pane);
card.show(controlPane,"面板一");

centerPane=new JPanel();
centerPane.setLayout(null);
centerPane.add(label);
centerPane.add(textField);

sureButton=new JButton("確定");
sureButton.setFont(font);
sureButton.addActionListener(this);

southPane=new JPanel();
southPane.setLayout(new FlowLayout());
southPane.add(sureButton);

pane.setBorder(new TitledBorder("歡迎來到中心面板"));
pane.add(southPane,BorderLayout.SOUTH);
pane.add(centerPane);

vsplitPane=new JSplitPane(JSplitPane.VERTICAL_SPLIT);
vsplitPane.setTopComponent(new JScrollPane(controlPane));
vsplitPane.setBottomComponent( log);
vsplitPane.setDividerLocation(320);
//button.addActionListener(this);
vsplitPane.setEnabled(false);

int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;  
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;  
add(vsplitPane);
setSize(630,530);
setLocation((screen_width - this.getWidth()) / 2,  
        (screen_height - this.getHeight()) / 2);  
setBackground(Color.LIGHT_GRAY);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBorder(new TitledBorder("模擬磁碟排程"));
setResizable(false);
setTitle("[email protected]夜空--模擬磁碟排程");  
}

public void actionPerformed(ActionEvent e){

  if(e.getSource()==sureButton){

      String str=textField.getText();
      if(str.trim().equals("")){ 
          JOptionPane.showMessageDialog(this, "磁軌號序列不能為空!", "提示", 
                  JOptionPane.WARNING_MESSAGE);
      }
      else{
          try{
              String[] buffer=str.split(" ");
              if(buffer.length>0){
                  for(int i=0;i<buffer.length;i++){
                      cidao[i]=Integer.parseInt(buffer[i]);

                  }
                  log.addLog("你輸入的磁軌序列為:"+str);
                  card.show(controlPane, "面板二");
              }
              else{
                  JOptionPane.showMessageDialog(this, "輸入的格式有誤", "提示", 
                          JOptionPane.WARNING_MESSAGE);
              }

          }
          catch(Exception e1){
              e1.printStackTrace();
              JOptionPane.showMessageDialog(this, "輸入的格式有誤", "提示", 
                      JOptionPane.WARNING_MESSAGE);
          }
      }
  }
 }

public static  int[] getCidao(){
    return cidao;
}


public  static void showCard(){
    card.show(controlPane,"面板一");
}
public static void main(String[]args){

    new DiskOperation();
}

}

執行效果