用JAVASwing實現模擬磁碟排程
阿新 • • 發佈:2018-12-26
通過使用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();
}
}
執行效果