package j2se.thread.demo; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * <p>Project:J2SE 的基础知识</p> * <p>Tile:多线程模拟银行转账 </p> * <p>Description: * 1.在同一个银行中的账户之间进行转账服务 , 站在银行的角度 , 不管咱们转 , 银行里面 * 的总金额不会变化 ; * * 2.将 A 账户里面的金额 , 转向 B 账户 ,这个过程不能被打断 , 需要加锁 , 也就是在同一时刻 * 只能有一个线程在 执行 转账 这段代码段 ; * * 3.通过 java.util.concurrent.locks.ReentrantLock 类中的方法 , 实现 加锁 ,保证线程同步 ; * * </p> * * @date 2014-06-04 * @author liwenkai * @version 1.0 * */ public class SynchBankTransfer00{ public static void main(String[] args){ // 最大转账金额 , 也是银行账户初始化金额 double initialBalance = 1000 ; String bankName = "招商银行" ; // 银行中的账户数量 int acctCounts = 100 ; Bank00 bk = new Bank00(bankName ,acctCounts , initialBalance ) ; for(int i = 0 ; i < acctCounts ; i++){ TransferRunnable00 tr = new TransferRunnable00( bk , i , initialBalance ) ; Thread thread = new Thread(tr , ".........线程名 = " + i +" ................") ; thread.start() ; } // System.out.printf("%10.5f , %d , %d%n ", 100.4677 , 60 , 99 ) ; // System.out.printf("%10.3f , %d , %d ", 999.4677 , 70 , 100 ) ; // // /** // 100.46770 , 60 , 99 // 999.468 , 70 , 100 // */ } } /** * 银行中的账户 */ class Account00{ // 账户ID private int accountId ; // 账户名 private String accountName ; // 账户里面的金额 private double balance ; // constructor methods public Account00(){ } public Account00( int accountId , String accountName, double balance) { this.accountId = accountId; this.accountName = accountName; this.balance = balance; } // gets and sets methods public int getAccountId() { return accountId; } public void setAccountId(int accountId) { this.accountId = accountId; } public String getAccountName() { return accountName; } public void setAccountName(String accountName) { this.accountName = accountName; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } @Override public String toString() { return "Account00 [accountId=" + accountId + ", accountName=" + accountName + ", balance=" + balance + "]"; } } /** * 银行 */ class Bank00{ private String bankName ; private final Account00[] account00s ; private double totalBalance ; private Lock lock = new ReentrantLock() ; // constructor methods /** * bankName:银行的名称 * acctCounts:初始化银行中的账户数量 * initialBalance:初始化银行账户中默认的金额 */ public Bank00(String bankName , int acctCounts , double initialBalance){ this.bankName = bankName ; account00s = new Account00[acctCounts] ; for(int i = 0 ; i < acctCounts ; i++){ account00s[i] = new Account00( i , "[email protected]_"+i , initialBalance) ; } } /** * 银行转账方法 * @param fromAccId 转出账户ID * @param toAccId 转入账户ID * @param transBalance 转账金额 */ public void transferAccount(int fromAccId , int toAccId , double transBalance){ if((account00s[fromAccId].getBalance() - transBalance) < 0 ) return ; //加锁,一直到解锁,这些代码不可能被打断 lock.lock() ; try{ System.out.println("---- Current Thread Name = " + Thread.currentThread().getName() + " , " +" Current Time = " + System.currentTimeMillis()) ; System.out.println("---- parameter [ fromAccId:" +fromAccId +" , " + " toAccId: " +toAccId+" , " + " transBalance:" + transBalance + "]") ; System.out.println("---------------------------------transfer out ---------------------------"); System.out.println("---- transfer out account before fromAccount["+fromAccId+"].balance = " + account00s[fromAccId].getBalance() ) ; account00s[fromAccId].setBalance(account00s[fromAccId].getBalance() - transBalance) ; System.out.println("---- transfer out account after fromAccount["+fromAccId+"].balance = " + account00s[fromAccId].getBalance() ) ; System.out.println("---------------------------------transfer in ---------------------------"); System.out.println("---- transfer in account before toAccount["+toAccId+"].balance = " + account00s[toAccId].getBalance() ) ; account00s[toAccId].setBalance(account00s[toAccId].getBalance() + transBalance) ; System.out.println("---- transfer in account after toAccount["+toAccId+"].balance = " + account00s[toAccId].getBalance()+"\r\n" ) ; // 查询出银行的总金额 System.out.println("---- totalBalance of bank = " +getTotalBalance()+" --------end---" ) ; }finally{ //解锁 lock.unlock() ; } } // 计算银行所有账户的总金额 public double getTotalBalance(){ double tmp = 0.0d ; for(Account00 ac : account00s){ tmp += ac.getBalance() ; } totalBalance = tmp ; return tmp ; } // 银行总的账户数 public int getAccountCounts(){ return account00s.length ; } // gets and sets methods public String getBankName() { return bankName; } public void setBankName(String bankName) { this.bankName = bankName; } public void setTotalBalance(double totalBalance) { this.totalBalance = totalBalance; } public Account00[] getAccount00s() { return account00s; } } /** * * 执行任务的线程体 */ class TransferRunnable00 implements Runnable{ private Bank00 bk ; private int fromAccId ; private int delay = 1000 ; private double maxTransValue ; // constructor 方法 ; public TransferRunnable00(Bank00 bk , int fromAccId , double maxTransValue ){ this.bk = bk ; this.fromAccId = fromAccId ; this.maxTransValue = maxTransValue ; } // public void run(){ try{ while(true){ int toAccId = (int)(bk.getAccountCounts()*Math.random()) ; double transBalance = maxTransValue*Math.random() ; bk.transferAccount(fromAccId, toAccId, transBalance) ; Thread.sleep((long)(delay*Math.random())) ; } }catch(InterruptedException e){ } } }
java 线程 SynchBankTransfer00
时间: 2024-10-29 10:46:23