代碼
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class BankerSwing { JFrame jf = new JFrame("銀行家算法"); JPanel jp1 = new JPanel(); JTextField jtf1, jtf2, jtf3, jtf4; JComboBox jcb1; JButton jb1, jb2, jb3, jb4; JTextArea jta1; private int numResource = 3; private int numThread = 100; private int p = 0; // 當前處理的線程 int[] Available = new int[numResource]; // 空閑資源 int[][] Max = new int[numThread][numResource]; // 最大需求資源 int[][] Allocation = new int[numThread][numResource]; // 占有資源 int[][] Need = new int[numThread][numResource]; // 需求資源 int[][] Request = new int[numThread][numResource]; // 申請資源 int[] Work = new int[numResource]; // 輔助空間 // 結果展示 public void ShowFrame(){ jf.setSize(530, 350); //大小 jf.setAlwaysOnTop(true); jf.setResizable(false);//不可拖動 jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 初始化 jtf1 = new JTextField(3); jtf2 = new JTextField(3); jtf3 = new JTextField(3); jtf4 = new JTextField(3); String s[] = {"Max","Allocation","Available","Request"}; jcb1 = new JComboBox(s); jb1 = new JButton("確定"); jb2 = new JButton("例子"); jb3 = new JButton("清零"); jb4 = new JButton("撤銷"); // 底部布局 jp1.add(jcb1); jp1.add(new JLabel("ID:")); jp1.add(jtf1); jp1.add(new JLabel("A:")); jp1.add(jtf2); jp1.add(new JLabel("B:")); jp1.add(jtf3); jp1.add(new JLabel("C:")); jp1.add(jtf4); jp1.add(jb1); jb1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == jb1) { if(jcb1.getSelectedItem() == "Allocation"){//設置已占用資源 try{ p = Integer.parseInt(jtf1.getText()); if (p > 4) { JOptionPane.showMessageDialog(jf, "進程ID在0-4之間!","提示",JOptionPane.WARNING_MESSAGE); jtf1.setText(""); return; } if (Integer.parseInt(jtf2.getText()) < 0 || Integer.parseInt(jtf3.getText()) < 0 || Integer.parseInt(jtf4.getText()) < 0) { JOptionPane.showMessageDialog(jf, "資源數不能小於0!", "提示", JOptionPane.WARNING_MESSAGE); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); return; } if(Integer.parseInt(jtf2.getText()) > Max[p][0] || Integer.parseInt(jtf3.getText()) > Max[p][1] || Integer.parseInt(jtf4.getText()) > Max[p][2]){ JOptionPane.showMessageDialog(jf, "占用資源大於最大需求資源(未定義最大需求資源)", "提示", JOptionPane.WARNING_MESSAGE); jtf1.setText(""); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); return; } Allocation[p][0] = Integer.parseInt(jtf2.getText()); Need[p][0] = Max[p][0] - Allocation[p][0]; Allocation[p][1] = Integer.parseInt(jtf3.getText()); Need[p][1] = Max[p][1] - Allocation[p][1]; Allocation[p][2] = Integer.parseInt(jtf4.getText()); Need[p][2] = Max[p][2] - Allocation[p][2]; } catch(Exception d) { JOptionPane.showMessageDialog(jf, "輸入有誤!請重新輸入!", "提示", JOptionPane.WARNING_MESSAGE); ShowData(); return; } ShowData(); jta1.append("\n\n 已占有資源設置成功!"); } else if (jcb1.getSelectedItem() == "Max") { try { p = Integer.parseInt(jtf1.getText()); if (p > 4) { JOptionPane.showMessageDialog(jf, "進程ID在0-4之間!", "提示", JOptionPane.WARNING_MESSAGE); jtf1.setText(""); return; } if (Integer.parseInt(jtf2.getText()) < 0 || Integer.parseInt(jtf3.getText()) < 0 || Integer.parseInt(jtf4.getText()) < 0) { JOptionPane.showMessageDialog(jf, "資源數不能小於0!", "提示", JOptionPane.WARNING_MESSAGE); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); return; } if(Integer.parseInt(jtf2.getText()) < Allocation[p][0] || Integer.parseInt(jtf3.getText()) < Allocation[p][1] || Integer.parseInt(jtf4.getText()) < Allocation[p][2]){ JOptionPane.showMessageDialog(jf, "最大需求資源小於已占有資源!", "提示", JOptionPane.WARNING_MESSAGE); jtf1.setText(""); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); return; } Max[p][0] = Integer.parseInt(jtf2.getText()); Need[p][0] = Max[p][0] - Allocation[p][0]; Max[p][1] = Integer.parseInt(jtf3.getText()); Need[p][1] = Max[p][1] - Allocation[p][1]; Max[p][2] = Integer.parseInt(jtf4.getText()); Need[p][2] = Max[p][2] - Allocation[p][2]; } catch(Exception d) { JOptionPane.showMessageDialog(jf, "輸入有誤!請重新輸入!", "提示", JOptionPane.WARNING_MESSAGE); ShowData(); return; } ShowData(); jta1.append("\n\n 最大需求設置成功!"); } else if (jcb1.getSelectedItem()=="Available"){//設置可用資源 try{ if (Integer.parseInt(jtf2.getText()) < 0 || Integer.parseInt(jtf3.getText()) < 0 || Integer.parseInt(jtf4.getText()) < 0) { JOptionPane.showMessageDialog(jf, "資源數不能小於0!", "提示", JOptionPane.WARNING_MESSAGE); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); return; } Available[0] = Integer.parseInt(jtf2.getText()); Available[1] = Integer.parseInt(jtf3.getText()); Available[2] = Integer.parseInt(jtf4.getText()); }catch(Exception d) { JOptionPane.showMessageDialog(jf, "您輸入有誤!請重新輸入!", "提示", JOptionPane.WARNING_MESSAGE); ShowData(); return; } ShowData(); jta1.append("\n\n 可用資源設置成功!"); } else if(jcb1.getSelectedItem() == "Request"){ try{ p = Integer.parseInt(jtf1.getText()); if (p > 4) { JOptionPane.showMessageDialog(jf, "進程ID在0-4之間!", "提示", JOptionPane.WARNING_MESSAGE); jtf1.setText(""); return; } if (Integer.parseInt(jtf2.getText()) < 0 || Integer.parseInt(jtf3.getText()) < 0 || Integer.parseInt(jtf4.getText()) < 0) { JOptionPane.showMessageDialog(jf, "資源數不能小於0!", "提示", JOptionPane.WARNING_MESSAGE); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); return; } Request[p][0] = Integer.parseInt(jtf2.getText()); Request[p][1] = Integer.parseInt(jtf3.getText()); Request[p][2] = Integer.parseInt(jtf4.getText()); }catch(Exception d) { JOptionPane.showMessageDialog(jf, "您輸入有誤!請重新輸入!", "提示", JOptionPane.WARNING_MESSAGE); ShowData(); return; } int[] order = new int[numThread]; if(bankerKernel(p, order)){ ShowData(); jta1.append("\n\n 通過安全性檢查!安全序列為:"); for(int i = 0; i < order.length; i++)//打印安全序列 jta1.append("P"+order[i]+" "); JOptionPane.showMessageDialog(jf, "申請成功,資源已經分配~~~","提示",JOptionPane.INFORMATION_MESSAGE); }else { ShowData(); for (int i = 0; i < numResource; i++) { Request[p][i] = 0; } JOptionPane.showMessageDialog(jf, "找不到安全序列! 不批准請求!", "提示", JOptionPane.WARNING_MESSAGE); } }else{ ShowData(); jta1.append("\n\n 系統資源不足!"); } } } }); // 確定按鍵功能設定 jp1.setBackground(new java.awt.Color(128,255,128)); // 右邊布局,豎直 Box vBox = Box.createVerticalBox(); vBox.add(Box.createVerticalStrut(60)); // 添加空白 vBox.add(jb2); vBox.add(Box.createVerticalStrut(20)); // 添加空白 vBox.add(jb3); vBox.add(Box.createVerticalStrut(20)); // 添加空白 vBox.add(jb4); jb2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == jb2){ init(); ShowData(); } } }); // 例子按鍵功能設定 jb3.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == jb3){ reset(); ShowData(); } } }); // 清零按鍵功能設定 jb4.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == jb4){ if(revocation()) JOptionPane.showMessageDialog(jf, "撤銷成功~~~","提示", JOptionPane.INFORMATION_MESSAGE); else JOptionPane.showMessageDialog(jf, "無撤銷內容!","提示", JOptionPane.WARNING_MESSAGE); ShowData(); } } }); // 撤銷按鍵功能設定 jf.add(jp1,"South"); // 布局底部 jf.add(vBox,"After");// 右邊 // 展示中間的文本 jta1= new JTextArea(); ShowData(); jta1.setLineWrap(true); jta1.setBackground(Color.white); jta1.setEditable(false); jf.add(jta1,BorderLayout.CENTER); // 結果展示 jf.setVisible(true); } // 展示數據 public void ShowData() { jta1.setText(" Max \tAllocation \t Need Available\n"); jta1.append("\n" + " 資源 " + " A B C " + " A B C " + " A B C " + " A B C"); jta1.append("\n 進程\n P0" + " " + + Max[0][0] + " " + Max[0][1] + " " +Max[0][2] + " " + " " + Allocation[0][0] + " " + Allocation[0][1] + " " + Allocation[0][2] + " " + " " + Need[0][0] + " " + Need[0][1] + " " + Need[0][2] + " " + " " + Available[0] + " " + Available[1] + " " + Available[2]); for (int i = 1; i < 5; i++) { jta1.append("\n\n P" + i + " " + " " + Max[i][0] + " " + Max[i][1] + " " + Max[i][2] + " " + " " + Allocation[i][0] + " " + Allocation[i][1] + " " + Allocation[i][2] + " " + " " + Need[i][0] + " " + Need[i][1] + " " + Need[i][2] + " "); } jtf1.setText(""); jtf2.setText(""); jtf3.setText(""); jtf4.setText(""); } // 算法核心流程 public boolean bankerKernel(int num, int[] order){ // 判斷資源申請的數量是否符合空閑資源和需要資源 for(int i = 0; i < numResource; i++){ if(Request[num][i] > Need[num][i]) { System.out.println("錯誤:進程P" + num + "的申請,超出最大需求量Need。"); return false; } else if(Request[num][i] > Available[i]){ System.out.println("錯誤:當前沒有足夠的資源可申請,進程P" + num + "需等待。"); return false; } } // 更新空閑資源,占用資源和需要資源 for (int i = 0; i < numResource; i++) { Allocation[num][i] += Request[num][i]; Available[i] -= Request[num][i]; Need[num][i] -= Request[num][i]; } // 安全性檢查 if(isSafe(order)){ return true; } // 不安全,返回申請資源前的狀態 for (int i = 0; i < numResource; i++) { Allocation[num][i] -= Request[num][i]; Available[i] += Request[num][i]; Need[num][i] += Request[num][i]; } return false; } // 安全性檢查 public boolean isSafe(int[]order){ int count = 0; // 安全的線程數量 int k = 0; int circle = 0; // 循環次數 boolean[] Finish = new boolean[numThread]; // 線程是否進入安全序列 for (int i = 0; i < numResource; i++) { Finish[i] = false; } copyWork(); while(true){ for (int i = 0; i < numThread; i++) { if(Finish[i] == false){ for (k = 0; k < numResource; k++) { if(Work[k] < Need[i][k]) break; } // 空閑資源滿足線程所需要的資源 if(k == numResource){ order[count++] = i; Finish[i] = true; // 釋放資源 for (int j = 0; j < numResource; j++) { Work[j] += Allocation[i][j]; } } } } circle++; if(count == numThread){ System.out.print("存在一個安全序列:"); for (int i = 0; i < numThread; i++){//輸出安全序列 System.out.print("P" + order[i] + " "); } System.out.println("故當前可分配!"); return true; } // 如果進入安全序列的線程數小於循環次數,說明不存在能安全完成的線程 if(count < circle){ System.out.println("警告:申請使得系統處於不安全狀態,申請失敗。"); return false; } } } // 使用輔助空間 public void copyWork(){ for (int i = 0; i < numResource; i++) { Work[i] = Available[i]; } } // 初始化一個例子 public void init(){ numThread = 5; numResource = 3; Available[0] = 3; Available[1] = 3; Available[2] = 2; Max[0][0] = 7; Max[0][1] = 5; Max[0][2] = 3; Max[1][0] = 3; Max[1][1] = 2; Max[1][2] = 2; Max[2][0] = 9; Max[2][1] = 0; Max[2][2] = 2; Max[3][0] = 2; Max[3][1] = 2; Max[3][2] = 2; Max[4][0] = 4; Max[4][1] = 3; Max[4][2] = 3; Allocation[0][0] = 0; Allocation[0][1] = 1; Allocation[0][2] = 0; Allocation[1][0] = 2; Allocation[1][1] = 0; Allocation[1][2] = 0; Allocation[2][0] = 3; Allocation[2][1] = 0; Allocation[2][2] = 2; Allocation[3][0] = 2; Allocation[3][1] = 1; Allocation[3][2] = 1; Allocation[4][0] = 0; Allocation[4][1] = 0; Allocation[4][2] = 2; for (int i = 0; i < numThread; i++) { for (int j = 0; j < numResource; j++) { Need[i][j] = Max[i][j] - Allocation[i][j]; } } } // 清零 public void reset(){ for (int i = 0; i < numThread; i++) { for (int j = 0; j < numResource; j++) { Max[i][j] = 0; Allocation[i][j] = 0; Need[i][j] = 0; Available[j] = 0; } } } // 撤回 public boolean revocation(){ if(Request[p][0] == 0 && Request[p][1] == 0 && Request[p][2] == 0) return false; for (int i = 0; i < numResource; i++) { Allocation[p][i] -= Request[p][i]; Need[p][i] = Max[p][i] - Allocation[p][i]; Available[i] += Request[p][i]; Request[p][i] = 0; } return true; } public static void main(String[] args) { BankerSwing B = new BankerSwing(); B.ShowFrame(); } }
結果截圖
1. 成功運行。
2. 申請成功后可以進行撤銷。
3. 若未成功申請無法進行撤銷操作。
4. 不安全,申請失敗。
5. 設置Allocation比Max大時。
6. 在已經有Allocation時,想修改Max數據,為了防止出錯。
7. 成功設置Max。
8. 成功設置Allocation。
9. 成功設置Available。