package j2se.thread.demo;
/**
* <p>Project:J2SE 的基础知识</p>
* <p>Tile:多线程模拟银行转账 </p>
* <p>Description:
* 1.在同一个银行中的账户之间进行转账服务 , 站在银行的角度 , 不管咱们转 , 银行里面
* 的总金额不会变化 ;
*
* 2.将 A 账户里面的金额 , 转向 B 账户 ,这个过程不能被打断 , 需要加锁 , 也就是在同一时刻
* 只能有一个线程在 执行 转账 这段代码段 ;
*
* 3.通过 synchronized 关键字 放到 方法上 , 或者 synchronized(this){} 代码块来 实现 加锁 ,保证线程同步 ;
*
* </p>
*
* @date 2014-06-07
* @author liwenkai
* @version 1.0
*
*/
public class SynchBankTransfer01{
public static void main(String[] args){
// 最大转账金额 , 也是银行账户初始化金额
double initialBalance = 1000 ;
String bankName = "招商银行" ;
// 银行中的账户数量
int acctCounts = 100 ;
Bank01 bk = new Bank01(bankName ,acctCounts , initialBalance ) ;
for(int i = 0 ; i < acctCounts ; i++){
TransferRunnable01 tr = new TransferRunnable01( bk , i , initialBalance ) ;
Thread thread = new Thread(tr , ".........线程名 = " + i +" ................") ;
thread.start() ;
}
}
}
/**
* 银行中的账户
*/
class Account01{
// 账户ID
private int accountId ;
// 账户名
private String accountName ;
// 账户里面的金额
private double balance ;
// constructor methods
public Account01(){
}
public Account01( 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 "Account01 [accountId=" + accountId + ", accountName="
+ accountName + ", balance=" + balance + "]";
}
}
/**
* 银行
*/
class Bank01{
private String bankName ;
private final Account01[] Account01s ;
private double totalBalance ;
// constructor methods
/**
* bankName:银行的名称
* acctCounts:初始化银行中的账户数量
* initialBalance:初始化银行账户中默认的金额
*/
public Bank01(String bankName , int acctCounts , double initialBalance){
this.bankName = bankName ;
Account01s = new Account01[acctCounts] ;
for(int i = 0 ; i < acctCounts ; i++){
Account01s[i] = new Account01( i , "accountName@_"+i , initialBalance) ;
}
}
/**
* 银行转账方法
* @param fromAccId 转出账户ID
* @param toAccId 转入账户ID
* @param transBalance 转账金额
*/
// 也可以 把 synchronized , 加到方法上 ,对整个方法进行加锁 (拿到的是对象锁) ;
// public synchronized void transferAccount(int fromAccId , int toAccId , double transBalance){
public void transferAccount(int fromAccId , int toAccId , double transBalance){
if((Account01s[fromAccId].getBalance() - transBalance) < 0 ) return ;
// 一般采用 synchronized(this) 代码块 来进行给相应的代码片段加锁 ,
// 加锁的范围能小则小 , 锁的范围太大的话影响效率 , (拿到的是对象锁)
synchronized(this){
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 = " + Account01s[fromAccId].getBalance() ) ;
Account01s[fromAccId].setBalance(Account01s[fromAccId].getBalance() - transBalance) ;
System.out.println("---- transfer out account after fromAccount["+fromAccId+"].balance = " + Account01s[fromAccId].getBalance() ) ;
System.out.println("---------------------------------transfer in ---------------------------");
System.out.println("---- transfer in account before toAccount["+toAccId+"].balance = " + Account01s[toAccId].getBalance() ) ;
Account01s[toAccId].setBalance(Account01s[toAccId].getBalance() + transBalance) ;
System.out.println("---- transfer in account after toAccount["+toAccId+"].balance = " + Account01s[toAccId].getBalance()+"\r\n" ) ;
// 查询出银行的总金额
System.out.println("---- totalBalance of bank = " +getTotalBalance()+" --------end---" ) ;
}
}
// 计算银行所有账户的总金额
public double getTotalBalance(){
double tmp = 0.0d ;
for(Account01 ac : Account01s){
tmp += ac.getBalance() ;
}
totalBalance = tmp ;
return tmp ;
}
// 银行总的账户数
public int getAccountCounts(){
return Account01s.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 Account01[] getAccount01s() {
return Account01s;
}
}
/**
*
* 执行任务的线程体
*/
class TransferRunnable01 implements Runnable{
private Bank01 bk ;
private int fromAccId ;
private int delay = 1000 ;
private double maxTransValue ;
// constructor 方法 ;
public TransferRunnable01(Bank01 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 线程 SynchBankTransfer01
最新推荐文章于 2021-11-29 17:31:32 发布