线程练习
1:
银行有一个账户。有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打
印账户余额。
问题:该程序是否有安全问题,如果有,如何解决?
【提示】 1,明确哪些代码是多线程运行代码,须写入run()方法 2,明确什么是共享数据。 3,明确多线程运行代码中哪些语句是操作共享数据的。
解答
public class LianxiTest { public static void main(String[] args) { Accoun accoun = new Accoun(0); BankL bankL1 = new BankL(accoun); BankL bankL2 = new BankL(accoun); bankL1.start(); bankL2.start(); } } class BankL extends Thread{ private Accoun accoun; public BankL(Accoun accoun){ this.accoun = accoun; } @Override public void run() { for(int i = 0; i < 3; i++){ accoun.deposit(1000); } } } class Accoun{ private double balance; public Accoun(double balance){ this.balance = balance; } public synchronized void deposit(double amt){ if( amt > 0){ balance += amt; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+": 存了钱 余额为: "+balance); } } }
2:
1.定义一个Account类 练习2 1)该Account类封装了账户编号(String)和余额(double)两个属性 2)设置相应属性的getter和setter方法 3)提供无参和有两个参数的构造器 4)系统根据账号判断与用户是否匹配,需提供hashCode()和equals()方法的重写 2.提供两个取钱的线程类:小明、小明’s wife 1)提供了Account类的account属性和double类的取款额的属性 2)提供带线程名的构造器 3)run()方法中提供取钱的操作 3.在主类中创建线程进行测试。考虑线程安全问题。
mport java.util.Objects; public class BankTestOneOne { public static void main(String[] args) { AccountTOne accountTOne = new AccountTOne("001", 1000); WithDrawThread withDrawThread = new WithDrawThread("老王", accountTOne, 500); withDrawThread.start(); AccountTOne accountTOne1 = new AccountTOne("002", 2000); WithDrawThread withDrawThread1 = new WithDrawThread("老李", accountTOne1, 300); withDrawThread1.start(); } } class AccountTOne{ private String accountId; // 账号 private double balance; // 余额 public AccountTOne(){}; public AccountTOne(String accountId, double balance){ this.balance = balance; this.accountId = accountId; } public String getNumber() { return accountId; } public void setNumber(String accountId) { this.accountId = accountId; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } @Override public String toString() { return "AccountTOne{" + "accountId='" + accountId + '\'' + ", balance=" + balance + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AccountTOne that = (AccountTOne) o; return Double.compare(that.balance, balance) == 0 && Objects.equals(accountId, that.accountId); } @Override public int hashCode() { return Objects.hash(accountId, balance); } } class WithDrawThread extends Thread{ private AccountTOne accountTOne; //设置取款额度 private double withDraw; public WithDrawThread(){}; public WithDrawThread(String name,AccountTOne accountTOne, double withDraw){ super(name); this.accountTOne = accountTOne; this.withDraw = withDraw; } @Override public void run() { synchronized(accountTOne){ if(accountTOne.getBalance() > withDraw){ System.out.println(Thread.currentThread().getName()+"取款成功, 金额为:"+withDraw); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } accountTOne.setBalance(accountTOne.getBalance()- withDraw); // 剩余钱数 }else{ System.out.println("取款金额超出上限"); } System.out.println(Thread.currentThread().getName()+"现在的余额为: "+ accountTOne.getBalance()); } } }