以银行取款经典案例来演示线程冲突现象。 银行取钱的基本流程基本上可以分为如下几个步骤。
    (1)用户输入账户、密码,系统判断用户的账户、密码是否匹配。
    (2)用户输入取款金额
    (3)系统判断账户余额是否大于取款金额
    (4)如果余额大于取款金额,则取钱成功;如果余额小于取款金额,则取钱失败。

    1. public class DrawMoneyDemo {
    2. public static void main(String[] args) {
    3. Account account=new Account("1234",1000);
    4. new DrawMoney("老公",account,800).start();
    5. new DrawMoney("老婆",account,800).start();
    6. }
    7. }
    8. /**
    9. * 账户类
    10. */
    11. class Account{
    12. //账号
    13. private String accountNo;
    14. //账户余额
    15. private double balance;
    16. public Account(){
    17. }
    18. public Account(String accountNo,double balance){
    19. this.accountNo=accountNo;
    20. this.balance=balance;
    21. }
    22. public String getAccountNo() {
    23. return accountNo;
    24. }
    25. public void setAccountNo(String accountNo) {
    26. this.accountNo = accountNo;
    27. }
    28. public double getBalance() {
    29. return balance;
    30. }
    31. public void setBalance(double balance) {
    32. this.balance = balance;
    33. }
    34. }
    35. /**
    36. * 取款线程
    37. */
    38. class DrawMoney extends Thread{
    39. //账号对象
    40. private Account account;
    41. //取款金额
    42. private double drawMoney;
    43. public DrawMoney(String name,Account account,double drawMoney){
    44. super(name);
    45. this.account=account;
    46. this.drawMoney=drawMoney;
    47. }
    48. @Override
    49. public void run() {
    50. //判断当前账户余额是否大于或等于取款金额
    51. if(this.account.getBalance()>=this.drawMoney){
    52. System.out.println(this.getName()+"取钱成功!吐出钞票:"+this.drawMoney);
    53. try {
    54. Thread.sleep(1000);
    55. } catch (InterruptedException e) {
    56. e.printStackTrace();
    57. }
    58. //更新账户余额
    59. this.account.setBalance(this.account.getBalance()-this.drawMoney);
    60. System.out.println("\t余额为:"+this.account.getBalance());
    61. }else{
    62. System.out.println(this.getName()+"取钱失败,余额不足");
    63. }
    64. }
    65. }

    image.png
    结果明显不对,这就是线程不同步的后果