线程安全经典案例:银行取钱问题
银行取钱的基本流程基本上可以分为如下几个步骤。
(1)用户输入账户、密码,系统判断用户的账户、密码是否匹配。
(2)用户输入取款密码
(3)系统判断账户余额是否大于取款余额
(4)如果余额大于取款余额,则取钱成功;如果余额小于取款余额,则取钱失败。
1、先定义一个账户类,该账户类封装了账号和余额两个实例变量。
public class Account {private String accountNo;private double balance;public Account() {}public Account(String accountNo, double balance) {super();this.accountNo = accountNo;this.balance = balance;}public String getAccountNo() {return accountNo;}public void setAccountNo(String accountNo) {this.accountNo = accountNo;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}@Overridepublic int hashCode() {return accountNo.hashCode();}@Overridepublic boolean equals(Object obj) {if(this==obj)return true;if(obj != null && obj.getClass() == Account.class){Account target=(Account)obj;return target.getAccountNo().equals(accountNo);}return false;}
}
2、提供一个取钱的线程类,该线程类根据根据执行账户、取钱数量进行取钱操作,取钱的逻辑是当其余额不足时无法提取现金,当余额足够时系统吐出钞票,余额减少。
public class DrawThread extends Thread{private Account account;private double drawAmount;public DrawThread(String name,Account account, double drawAmount) {super(name);this.account = account;this.drawAmount = drawAmount;}public void run(){if(account.getBalance()>=drawAmount){System.out.println(getName()+":取钱成功!吐出钞票:"+drawAmount);try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}account.setBalance(account.getBalance()-drawAmount);System.out.println("\t余额为:"+account.getBalance());}else{System.out.println(getName()+"取钱失败!余额不足!");}}
}
3、主程序创建一个账户,启动两个线程,执行取钱操作。
public class DrawTest {public static void main(String[] args) {Account acct=new Account("0329",1000);new DrawThread("老张",acct,800).start();new DrawThread("老王",acct,800).start();}
}
后台输出:老张:取钱成功!吐出钞票:800.0老王:取钱成功!吐出钞票:800.0余额为:200.0余额为:-600.0
注意:程序中有两个并发线程在修改Account对象,系统恰好在try-catch处执行线程切换,切换给另一个修改Account对象的线程,所以出现了问题。
解决方案:
Java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块。同步代码块的语法格式如下:
synchronized(obj){}
synchronized(account){if(account.getBalance()>=drawAmount){System.out.println(getName()+":取钱成功!吐出钞票:"+drawAmount);try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}account.setBalance(account.getBalance()-drawAmount);System.out.println("\t余额为:"+account.getBalance());}else{System.out.println(getName()+"取钱失败!余额不足!");}
}
控制台输出:
老张:取钱成功!吐出钞票:800.0余额为:200.0老王取钱失败!余额不足!
线程安全经典案例:银行取钱问题相关推荐
- 线程同步之模拟银行取钱实例
线程同步的机制就是队列和锁,把共享的资源加上一把锁,然后把线程进行排队,实现安全的线程.下面为大家模拟银行取钱的实例,代码如下: public class Unsafebank {public s ...
- 经典的同步问题(银行取钱)
银行取钱问题是非常经典的同步问题,如果不采用同步方法,可能也不会发生错误,但就是那小概率事件就可以称之为BUG吧. 没有使用同步方法的代码如下: public class ErrorTest{publ ...
- Java线程安全和线程同步——以银行取钱为例
Java线程安全和线程同步(银行取钱案例) 一.线程安全问题 案例:银行多用户操作同一账户 public class SafeBank {public static void main(String[ ...
- java多线程学习二、安全与不安全示例:12306买票和银行取钱、java内存模型、内存可见性、线程同步块和方法
文章目录 前言 1. 什么是块,分为几种 2. 静态块与构造块的区别 一. 举例说明:并发情况下,线程不安全 1. 示例1:unsafe12306取票 2. 示例2:unsafe银行取钱 二.线程不安 ...
- java银行安全性_Java使用同步方法解决银行取钱的安全问题案例分析
本文实例讲述了Java使用同步方法解决银行取钱的安全问题.分享给大家供大家参考,具体如下: 一 点睛 与同步代码块对应,Java的多线程安全支持还提供了同步方法,同步方法就是使用synchronize ...
- html中js计算百钱百鸡,JS经典案例之百钱百鸡
今天我们来回顾一下JS的经典案例之百钱百鸡 题目 公鸡5元钱一只,母鸡3元钱一只,小鸡3只一元钱,用100元钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100元钱 ...
- java银行取款_Java写简单的银行取钱系统
按ctrl+a 选中所有的代码删除,再复制下面的代码输入即可 import java.util.Scanner; public class 简单的银行取钱系统 //class的名字可以自己新建和这个一 ...
- java多线程银行取钱_用java线程同步实现银行取款和存款。
题目是:编写程序实现线程的同步.假设一个银行的ATM机,它可以允许用户存款也可以取款.现在一个账户上有200元,用户A和用户B都拥有在这个账户上存款和取款的权利.用户A将存入100元... 题目是:编 ...
- java多线程学习一、线程介绍、线程创建的3种方式、lambda创建方式、线程状态、线程示例:12306买票和银行取钱
文章目录 前言 一.线程简介 1.概述 2.进程.线程 区别 在这里插入图片描述 3. 核心概念 二. 线程创建 1.概述 2. 第一种方式继承Thread 1) 继承Thread 2) 示例:下载图 ...
最新文章
- 2022-2028年中国干洗行业市场全景调研与投资前景预测报告
- 知道PHP期末答案,PHP期末练习(参考答案).doc
- 树莓派3b+目标检测: tflite 运行 mobilenet ssd
- 中国石油管道科技研究中心2014届应届毕业生招聘(软件工程师岗)
- python函数编程训练题_Python文件与函数练习题
- html中select标签刷新后不回到默认值而是保持之前选择值
- 第一阶段 03Java的基本数据类型
- 微软TypeScript 3.0重磅发布!扶我起来,我还学得动
- Linux进程实践(3) --进程终止与exec函数族
- 如何才能通过一线互联网公司面试?全网疯传
- python launcher下载_Python flauncher包_程序模块 - PyPI - Python中文网
- Adobe Dreamweaver Adobe Photoshop CS5 amtlib.dll 文件
- xctf攻防世界 REVERSE 高手进阶区 re2-cpp-is-awesome
- 基于XSSFWorkbook 实现POI设置指定列为文本格式
- 《牛奶可乐经济学》读书笔记 | 用经济学点亮生活
- 原码,反码,补码是什么?
- GVM踩坑记录之 Failed to find port_list ‘33d0cd82-57c6-11e1-8ed1-406186ea4fc5‘
- 互联网月饼大赏,你最喜欢哪家的?
- terminate called without an active exception异常
- 手机号码和姓名脱敏(加密*)
热门文章
- 21世纪网络费用明明过分便宜,为什么网络运营商却收取过高的费用?
- 台式机设成仅计算机,台式机怎么设置局域网共享
- 代码工程必备能力—Commit 规范
- 设置Pycharm/IDEA背景颜色为护眼色
- skype安卓手机版_微信支付支持手机号转账,安卓7.08内测版上线!
- 正在更新office,然后一直打不开
- 博士申请 | 新加坡管理大学庞观松助理教授招收机器学习方向全奖博士生
- 读《论个人在历史上的作用问题》(普列汉诺夫)
- Qt音视频开发22-通用GPU显示
- python连接linux堡垒机_Python之路:堡垒机实例以及数据库操作