package com.owen.util.owenThread.Bank;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
@SuppressWarnings("serial")
public class SuzhouBank extends JPanel implements BankFunction, ActionListener {
/**
* 银行数据,所有银行职员对它的操作必须要求是同步的
* */
private BankData bankData = null;
private final int MaxExtract = 10000;
/**
* 五个UI控件,分别用于显示: 当前银行的总存储额 存款按钮 提款按钮 存款、提款金额 当前银行职员的工作状态
* */
private JTextField currentMoneyField = null;
private JButton storageButton = null;
private JButton extractButton = null;
private JTextField s_e_MoneyField = null;
private JList workStatusLED = null;
/**
* 定义银行职员的信息: 职员总数为5名,共当前银行共有5个职员线程在并行进行业务办理 Vector容器,用于保存这五名银行职员的对象
* Vector容器,用于保存五名银行职员当前的工作状态
* */
private final int bankStaffCount = 5;
private Vector<BankStaff> bankStaffs = null;
private Vector<String> staffWorkStatus = null;
/**
* 银行经理
* */
private BankManager bm = null;
/**
* 当天接待的客户的ID,这个ID是递增的,每次点击"存款,提款"按钮时,都分别为增加1
* */
private int customerId = 0;
/**
* 客户队列,每次来一位客户时,都先将其放到客户队列中,然后由银行经理分配由哪位银行职员为其服务
* */
private Vector<CustomerInfo> customer_queue = null;
/**
* 构造“苏州银行” UI构造 职员构造 经理构造
* */
public SuzhouBank() {
/**
* 创建 银行数据对象 银行职员容器 银行职员状态容器 客户队列
* */
bankData = new BankData();
bankStaffs = new Vector<BankStaff>();
staffWorkStatus = new Vector<String>();
customer_queue = new Vector<CustomerInfo>();
/**
* 创建具体的每一个银行职员对象,并将其放入容器中
* */
for (int i = 0; i < bankStaffCount; i++) {
BankStaff bs = new BankStaff(i, this);
bankStaffs.add(bs);
}
/**
* 创建银行的相关UI控制,并简单布局
* */
currentMoneyField = new JTextField(64);
currentMoneyField.setBackground(Color.LIGHT_GRAY);
currentMoneyField.setEditable(false);
s_e_MoneyField = new JTextField(16);
s_e_MoneyField.setBackground(Color.green);
storageButton = new JButton("存款");
extractButton = new JButton("提款");
this.setLayout(new BorderLayout());
workStatusLED = new JList();
this.add(currentMoneyField, "North");
this.add(s_e_MoneyField, "South");
this.add(storageButton, "East");
this.add(extractButton, "West");
this.add(new JScrollPane(workStatusLED), "Center");
storageButton.addActionListener(this);
extractButton.addActionListener(this);
/**
* 创建银行经理,并将其设置为后台守护,即银行经理不会直接面对客户,只是分配客户队列
* */
bm = new BankManager(this);
/**
* 银行后台监控,显示当前存储额及职员的工作状态
* */
new BankMonitor(this);
}
// ///////////////////////////////////////////////////////////////////
/* UI控制方法 */
/**
* 针对“存款,提款”两个按钮的具体响应方法
* */
@Override
public void actionPerformed(ActionEvent e) {
/**
* 根据按钮,汇总出当前客户需要的服务内容,并组成一个客户对象
* */
String operName = null;
if (e.getSource() == storageButton) {
operName = "存款";
} else if (e.getSource() == extractButton) {
operName = "提款";
} else {
currentMoneyField.setText("当前不支持该操作");
currentMoneyField.setBackground(Color.red);
return;
}
int iMoney = 0;
try {
iMoney = Integer.parseInt(s_e_MoneyField.getText());
} catch (Exception e2) {
s_e_MoneyField.setText("非法数值");
s_e_MoneyField.setBackground(Color.red);
return;
}
/**
* 具体构建出一个客户对象,这里需要客户的ID,客户要操作的金额,及具体服务内容(是存款还是提款)
* */
CustomerInfo ci = new CustomerInfo(++customerId, iMoney, operName);
/**
* 当构建出具体的客户对象时,需要将其同步的添加到客户队列中
*
* 说明: 操作客户队列的只有两个地方, 一是银行的“取号机”,取号机吐出一个号,即表示新增加了一位客户
* 二是银行经理,他需要从当前的客户队列中,将当前队列中的所有客户分配到每一个银行职员手中
*
* 取号机,银行经理,二者对客户队列的操作是要求同步的,即同一时刻,要么是取号机在添加客户到其中,
* 要么是银行经理将当前队列中的这批客户取出(取出,即从队列中将这批客户拿走,拿走之后,队列为空)
*
* 取号机添加客户的操作为下述代码,银行经理取客户的操作为方法 CustomerQueue,
* 二者同时设置到代码同步块,即对“当前银行的客户队列进行同步”
* */
synchronized (this.customer_queue) {
customer_queue.add(ci);
System.out.println("苏州银行接收了一位客户:" + ci.getCus_id()
+ ci.getOperName());
}
}
// ///////////////////////////////////////////////////////////////////
/* 业务控制方法 */
/**
* 银行经理提取客户队列的方法 这里设置了对客户队列的同步,即同一时刻,要么经理在操作之,要么取号机在操作之
*
* 取出当前的队列内容之后,清空当前队列
* */
@Override
public Vector<?> CustomerQueue() {
synchronized (this.customer_queue) {
Vector<?> curCusQueue = (Vector<?>) customer_queue.clone();
customer_queue.clear();
return curCusQueue;
}
}
/**
* 存款操作,提款操作,显示银行当前总存储额这三项操作,都涉及到了“银行数据”
*
* 即这三项操作,同一时刻,只能有一项操作被执行,即要求设置为同步,具体如下:
*
* 存款操作,提款操作,具体是由银行职员来完成的,即五个银行职员(五个线程)为银行数据的操作要求是并行的
*
* 显示银行当前总存储额的操作,是由银行经理(又一个线程)来完成的
*
* 如是而言,总计有6个线程,需要对“银行数据”进行并行操作,而同一时刻只要求有其中一个线程执行相关操作,
* 故,直接将银行的三个方法 存款 提款 存储额 显示,同时设置为同步
*
*
* 以下即为三个同步接口的具体实现
* */
/**
* 实现存钱接口
* */
@Override
public synchronized void Storage(int i) {
int currentMoney = bankData.getTotalMoney();
bankData.setTotalMoney(currentMoney + i);
}
/**
* 实现取钱接口
* */
@Override
public synchronized void Extract(int i) {
int currentMoney = bankData.getTotalMoney();
bankData.setTotalMoney(currentMoney - i);
}
@Override
public synchronized int StorageAmount() {
String totalMoney = new Integer(bankData.getTotalMoney()).toString();
currentMoneyField.setText("中国银行苏州分行当前存储额为: " + totalMoney);
return bankData.getTotalMoney();
}
@Override
public synchronized boolean MoneyApproval(int money) {
if (money >= MaxExtract || money > StorageAmount()) {
System.out.println("一次性提款金额过多,需要等银行经理审批");
return true;
}
return false;
}
@Override
public synchronized void ApprovalPass() {
bankData.setTotalMoney(bankData.getTotalMoney() + MaxExtract * 10);
}
/**
* 此方法为获取银行当前的所有职员对象,该职员对象在创建出之后,
* 只会由银行经理去读取 故这里不会涉及到同步问题
* */
@Override
public Vector<?> AllBankStaffs() {
return bankStaffs;
}
/**
* 该方法是由当前所有银行职员的服务状态显示到银行的LED屏幕上,
* 同样只是由后台监控去调用 不涉及到同步问题
* */
@Override
public void StaffWorkStatus() {
staffWorkStatus.clear();
for (BankStaff bs : bankStaffs) {
staffWorkStatus.add(bs.serviceStatus());
}
((JList) workStatusLED).setListData(staffWorkStatus);
}
}
- 1
- 2
前往页