- import java.awt.BorderLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- import javax.swing.JScrollPane;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- /**
- * 线程同步
- * 我们模拟一个银行存储过程来证明线程同步的必要性以及在Java中进行线程同步的方法
- * 重点:synchronized 修饰符
- * @author 五斗米
- * @blog <a href="http://blog.csdn.net/mq612">http://blog.csdn.net/mq612
- */
- public class TestMain5 extends JFrame {
- private MyAccounts myAccounts = null; // 我的帐号
- private JTextField text = null; // 银行存款数额显示
- private JTextArea textArea = null; // 交易过程显示
- private JButton button = null; // 开始模拟交易的按钮
- /**
- * 构造一个银行存取款界面
- */
- public TestMain5(){
- super("线程同步测试");
- myAccounts = new MyAccounts();
- text = new JTextField(Integer.toString(myAccounts.inquire()), 10); // 我们在银行中的初始存款为100
- textArea = new JTextArea();
- textArea.setText("交易日志:");
- JScrollPane sp = new JScrollPane(textArea);
- button = new JButton("开始交易");
- button.addActionListener(new ActionListener(){
- public void actionPerformed(ActionEvent e) {
- new Bank("钟楼支行", myAccounts, Bank.DEAL_SAVING, 800);
- new Bank("高新支行", myAccounts, Bank.DEAL_SAVING, 1300);
- new Bank("小寨支行", myAccounts, Bank.DEAL_FETCH, 200);
- new Bank("雁塔支行", myAccounts, Bank.DEAL_FETCH, 400);
- new Bank("兴庆支行", myAccounts, Bank.DEAL_SAVING, 100);
- new Bank("土门支行", myAccounts, Bank.DEAL_FETCH, 700);
- }
- });
- JPanel pane = new JPanel();
- pane.add(text);
- pane.add(button);
- this.getContentPane().add(pane, BorderLayout.NORTH);
- this.getContentPane().add(sp);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- this.setSize(300, 200);
- this.setLocationRelativeTo(null);
- this.setVisible(true);
- }
- /**
- * 银行交易大厅类
- * 一般银行都会有N个交易大厅,这些大厅可以同时处理多笔业务,这正好符合多线程的特点
- */
- class Bank extends Thread{
- /**
- * 静态字段:用于表示储存
- */
- public static final int DEAL_SAVING = 0;
- /**
- * 静态字段:用于表示提取
- */
- public static final int DEAL_FETCH = 1;
- private int buy = Bank.DEAL_FETCH; // 默认使取款
- private int count = 0;
- private MyAccounts myAccounts = null; // 我的帐号
- /**
- * 构造这个银行交易大厅
- * @param name 这个交易大厅的名称
- * @param myAccounts 我的银行帐号
- * @param buy 行为,参考字段:DEAL_SAVING或DEAL_FETCH
- * @param count 钱的数量
- */
- public Bank(String name, MyAccounts myAccounts, int buy, int count){
- super(name);
- this.myAccounts = myAccounts;
- this.buy = buy;
- this.count = count;
- this.start();
- }
- public void run(){
- int $count = 0;
- if(buy == Bank.DEAL_SAVING){ // 如果是存款业务
- $count = myAccounts.saving(count);
- }else if(buy == Bank.DEAL_FETCH){ // 如果是取款业务
- $count = myAccounts.fetch(count);
- }
- text.setText(Integer.toString($count));
- textArea.append("\\n" + this.getName() + " " + (buy == Bank.DEAL_SAVING ? "存款": "取款") + " 金额:" + count + " 结余:" + $count);
- }
- }
- /**
- * 我的帐号
- * 进行同步测试
- */
- class MyAccounts{
- private Integer count = 1100;
- public MyAccounts(){
- }
- /**
- * 查询我的帐号
- */
- public int inquire(){
- synchronized (count){
- return count;
- }
- }
- /**
- * 存款业务
- * @param c 存款的数量
- * @return 业务办理完成后的数量
- */
- public int saving(int c){
- synchronized (count){
- //return count += c; // 为了能更好的观察,我们将这个简洁的语句注释掉
- int $count = inquire(); // 先查询帐户中的存款
- $count += c;
- try {
- Thread.sleep(1000); // 为了更好的观察,使业务在此停顿1秒钟
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- count = $count; // 最后将总数储存起来
- return inquire(); // 返回最新的存款数
- }
- }
- /**
- * 取款业务
- * @param c 取款的数量
- * @return 业务办理完成后的数量
- */
- public int fetch(int c){
- synchronized (count){
- //return count -= c; // 为了能更好的观察,我们将这个简洁的语句注释掉
- int $count = inquire(); // 先查询帐户中的存款
- $count -= c;
- try {
- Thread.sleep(1000); // 为了更好的观察,使业务在此停顿1秒钟
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- count = $count; // 最后将总数储存起来
- return inquire(); // 返回最新的存款数
- }
- }
- }
- public static void main(String [] args){
- new TestMain5();
- }
- }
- //该片段来自于http://www.codesnippet.cn/detail/170420132859.html
来源: http://www.codesnippet.cn/detail/170420132859.html