使用Lock和Condition来实现线程同步

来源:互联网 发布:mac玩英雄联盟国服 编辑:程序博客网 时间:2024/06/14 16:03

最近同事在用线程,探索一下线程同步

public class SynchBankTest { public static final int NACCOUNTS = 100; public static final double INITIAL_BALANCE = 1000; public static void main(String[] args) {  Bank2 b = new Bank2(NACCOUNTS, INITIAL_BALANCE);  int i;  for (i = 0; i < NACCOUNTS; i++) {   TransferRunable2 r = new TransferRunable2(b, i, INITIAL_BALANCE);   Thread t = new Thread(r);   t.start();  } }}class TransferRunable2 implements Runnable { private Bank2 bank; private int fromAccount; private double maxAmount; private int DELAY = 10; /**  * 转账线程实现类构造方法  *  * @param b  *            转账银行  * @param from  *            转出账户  * @param max  *            每笔转账最大金额  */ public TransferRunable2(Bank2 b, int from, double max) {  bank = b;  fromAccount = from;  maxAmount = max; } public void run() {  try {   while (true) {    int toAccount = (int) (bank.size() * Math.random());    double amount = maxAmount * Math.random();    bank.transfer(fromAccount, toAccount, amount);    Thread.sleep((int) (DELAY * Math.random()));   }  } catch (Exception e) {   e.printStackTrace();  } }}class Bank2 { //构建一个可被用来保护临界区的可重入锁 private Lock BankLock; private Condition sufficient; private final double[] accounts; /**  * 银行类  *  * @param n  *            账户数量  * @param initialBalance  *            账户初始余额  */ public Bank2(int n, double initialBalance) {  BankLock = new ReentrantLock();  //余额不足的条件变量  sufficient = BankLock.newCondition();  accounts = new double[n];  for (int i = 0; i < accounts.length; i++) {   accounts[i] = initialBalance;  } } /**  * 转账方法  *  * @param from  *            转出账户  * @param to  *            转入账户  * @param amount转账金额  */ public void transfer(int from, int to, double amount) {  BankLock.lock();  try {   while (accounts[from] < amount)    sufficient.await();//余额不足线程等待   System.out.println(Thread.currentThread().getName());   accounts[from] -= amount;   System.out.printf("%10.2f from %d to %d", amount, from, to);   accounts[to] += amount;   System.out.printf("Total Balance %10.2f%n", getTotalBalance());   sufficient.signalAll();//唤醒等待线程  } catch (Exception e) {   e.printStackTrace();  } finally {   BankLock.unlock();//释放锁  } } /**  * 获取所有账户余额之和  *  * @return 总余额  */ public double getTotalBalance() {  BankLock.lock();  try {   double sum = 0;   for (double a : accounts) {    sum += a;   }   return sum;  } finally {   BankLock.unlock();  } } /**  * 获取该银行有多少账户  *  * @return 账户数量  */ public int size() {  return accounts.length; }}    }