JavaSE 用Lock实现10个线程随机选择两个账户进行转账

题目如下:模拟银行转账业务, 有10个账户,每个账户初始金额为10000,有10个线程随机选择两个账户进行转账,每次转的金额是1000以内的. 每个线程转100次. 最后输出10个账户的总金额。

代码分为三个模块:主程序、线程和单个银行账户;

package com.gcs.AccountTest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

public class Main {

	public static void main(String[] args) {
		List accountList = new ArrayList();	
		MapaccLock = new HashMap();
		
		//10个账户;
		Account acc = null;
		for (int i = 0; i < 10; i++) {
			acc = new Account(String.valueOf(i+1));
			accountList.add(acc);
			accLock.put(acc, new ReentrantLock());
		}	
		
		//10个线程;
		List threadList = new ArrayList();
		for (int i = 0; i < 10; i++) {
			threadList.add(new AccountThread(accountList, accLock));
		}
		
		for (int i = 0; i < 10; i++) {
			threadList.get(i).start();
		}
		
		//等待10个线程运行结束;
		for (int i = 0; i < 10; i++) {
			try {
				threadList.get(i).join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}		
		
		int total = 0;
		for (int i = 0; i < 10; i++) {
			System.out.println("第" + (i+1) + "个账户" + accountList.get(i));
			total += accountList.get(i).getMoney();
		}
		System.out.println("总金额:"+total);
	}

}
package com.gcs.AccountTest;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AccountThread extends Thread {
	
	//存储10个账户;
	private ArrayList accList = null;
	
	//每个账户对应一个锁,使得一个线程仅锁当前要操作的两个账户对应的锁;
	MapaccLock = null;
	Random random = new Random();
	int acc1 = 0;
	int acc2 = 0;
	int money = 0;
	
	public AccountThread(List account, MapaccLock) {
		this.accList = (ArrayList)account;
		this.accLock = accLock;
	}
	
	private void acquireLocks(Lock lockA,Lock lockB) throws InterruptedException{
        while(true){
            boolean bLockA=false;
            boolean bLockB=false;
            try {
            	bLockA=lockA.tryLock();
            	bLockB=lockB.tryLock();
            }finally {
                if(bLockA&&bLockB)
                	return;
                else if (bLockA)
                	lockA.unlock();
                else if (bLockB)
                	lockB.unlock();
            }
            Thread.sleep(1);
        }
    }
	
	public void run() {
		
		for(int i = 0; i < 100; i++) {
			acc1= random.nextInt(10);
			acc2 = random.nextInt(10);
			//禁止相同账户相互转账;
			while(acc1 == acc2) {
				acc2 = random.nextInt(10);
			}
			money = random.nextInt(1000);

			try {
				acquireLocks(accLock.get(accList.get(acc1)), accLock.get(accList.get(acc2)));
				if(accList.get(acc1).getMoney() > money) {
					accList.get(acc1).drawMoney(money);
					accList.get(acc2).saveMoney(money);		
				}
				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}finally {
				accLock.get(accList.get(acc1)).unlock();
				accLock.get(accList.get(acc2)).unlock();
			}		
		}
	}
}
package com.gcs.AccountTest;

public class Account {
	private String name = "";
	private int money = 10000;
	
	public Account(String name) {
		this.name = name;
	}
	
	public void saveMoney(int money) {
		this.money += money;
	}
	
	public void drawMoney(int money) {
		this.money -= money;
	}
	
	public int getMoney() {
		return money;
	}
	
	public String toString() {
		return String.valueOf(money);
	}
}

运行结果:

JavaSE 用Lock实现10个线程随机选择两个账户进行转账_第1张图片JavaSE 用Lock实现10个线程随机选择两个账户进行转账_第2张图片

你可能感兴趣的:(Java类)