多线程同步机制练习之银行存钱

  1 package day2_4;
  2 
  3 import java.util.concurrent.locks.ReentrantLock;
  4 
  5 /**
  6  * 银行有一个账户。
  7  * 两个储户向同一个账户里存钱,每个储户都是存3000元,分三次,每次存1000。
  8  * 每次存完打印账户余额
  9  *
 10  * 分析:
 11  * 1.是多线程问题吗?  是,两个储户线程
 12  * 2.是否有共享数据?  有,同一个账户(或账户余额)
 13  * 3.是否有线程安全问题? 有
 14  * 4.如何解决线程安全问题? 同步机制:有三种方式
 15  *
 16  *
 17  * @Author Tianhao
 18  * @create 2021-02-05-18:21
 19  */
 20 public class AccountTest {
 21     public static void main(String[] args) {
 22         Account acct = new Account(0);
 23         Customer c1 = new Customer(acct);
 24         Customer c2 = new Customer(acct);
 25         c1.setName("客户1");
 26         c2.setName("客户2");
 27         c1.start();
 28         c2.start();
 29     }
 30 
 31 }
 32 
 33 //账号
 34 class Account {
 35     //余额
 36     private double balance = 0;
 37 
 38     public Account(double balance) {
 39         this.balance = balance;
 40     }
 41 
 42     private ReentrantLock lock = new ReentrantLock();
 43 
 44     //存钱操作
 45     //这里虽然线程类是继承Thread方式创建,但同步方法上没有static修饰
 46     //因为这个方法所在Account类的对象acct是多个线程共享的,就可以用this作为同步监视器
 47     //解决线程安全问题:方式一:使用同步方法
 48 //    public synchronized void deposit(double amt) {
 49 //        if (amt > 0) {
 50 //            balance += amt;
 51 //            try {
 52 //                Thread.sleep(1000);
 53 //            } catch (InterruptedException e) {
 54 //                e.printStackTrace();
 55 //            }
 56 //            System.out.println( Thread.currentThread().getName() + ":存钱成功。余额:" + balance);
 57 //        }
 58 //    }
 59 
 60     //解决线程安全问题:方式二:使用同步代码块
 61     public void deposit(double amt) {
 62         synchronized (this) {
 63             if (amt > 0) {
 64                 balance += amt;
 65                 try {
 66                     Thread.sleep(1000);
 67                 } catch (InterruptedException e) {
 68                     e.printStackTrace();
 69                 }
 70                 System.out.println(Thread.currentThread().getName() + ":存钱成功。余额:" + balance);
 71             }
 72         }
 73     }
 74 
 75 
 76     //解决线程安全问题:方式三:使用lock方法
 77 //    public synchronized void deposit(double amt) {
 78 //        try {
 79 //            lock.lock();
 80 //            if (amt > 0) {
 81 //                balance += amt;
 82 //                try {
 83 //                    Thread.sleep(1000);
 84 //                } catch (InterruptedException e) {
 85 //                    e.printStackTrace();
 86 //                }
 87 //                System.out.println( Thread.currentThread().getName() + ":存钱成功。余额:" + balance);
 88 //            }
 89 //        }finally {
 90 //            lock.unlock();
 91 //        }
 92 //    }
 93 
 94     public double getBalance() {
 95         return balance;
 96     }
 97 }
 98 //储户
 99 class Customer extends Thread{
100     private Account acct;
101     //将Account对象作为参数传入到构造器,这样就保证了创建的
102     // 每个Customer对象都是同一个Account对象
103     public Customer(Account acct) {
104         this.acct = acct;
105     }
106 
107     @Override
108     public void run() {
109         for (int i = 0; i < 3; i++) {
110             acct.deposit(1000);
111         }
112     }
113 }

 

上一篇:java+mybatis实现一个简单的银行系统,实现存取款与账户查询


下一篇:可变数据