java 线程 SynchBankTransfer01

package j2se.thread.demo;


/**
 * <p>Project:J2SE 的基础知识</p>
 * <p>Tile:多线程模拟银行转账 </p>
 * <p>Description: 
 *    1.在同一个银行中的账户之间进行转账服务 , 站在银行的角度 , 无论咱们转 , 银行里面
 *      的总金额不会变化 ;
 *      
 *    2.将 A 账户里面的金额 , 转向 B 账户 ,这个过程不能被打断 , 须要加锁 , 也就是在同一时刻
 *      仅仅能有一个线程在 运行 转账 这段代码段 ;
 *      
 *    3.通过 synchronized keyword 放到 方法上 , 或者 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()+"
" ) ;
			
			
			// 查询出银行的总金额 
			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){
			
		}
		
	}	
}





原文地址:https://www.cnblogs.com/wgwyanfs/p/7065097.html