java多线程ReenrrantLock用法

来源:互联网 发布:软件分享论坛 app 编辑:程序博客网 时间:2024/05/29 18:59

银行的账号问题,100个账户,每个账户拥有1000¥。各个账户之间来回转账,但是总的转账金额不变

  1. 使用锁,就不能使用带资源的try语句。
  2. 当条件对象调用了await()方法后,该线程处于等待状态,必须等待另一个线程调用singalAll()方法唤醒该线程,唤醒时该线程处于阻塞状态。
  3. signal随机解除等待状态中的某个线程。
package test2;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Bank {    private final double[] accounts;    private Lock bankLock;  //锁对象    private Condition sufficientFunds;  //条件对象,用来表达是否是余额充足    public Bank(int n, double initialBance) {        accounts = new double[n];        for (int i = 0; i < accounts.length; i++) {            accounts[i] = initialBance;        }        bankLock = new ReentrantLock();        sufficientFunds = bankLock.newCondition();    }    public void transfer(int from, int to, double amount) {        /*  确保任意时刻只有一个线程进入临界区。*/        bankLock.lock();            try {        /*判断余额是否充足,入宫不充足,则线程进入等待状态。*/            while (accounts[from] < amount) {                /*                 * 等待获得锁的线程和调用await方法的线程存在本质的不同。                 * 一旦一个线程调用await方法,它进入该条件的等待集。                 * 当锁可以用时,该线程不能马上解除阻塞。相反,它处于阻塞状态,直到另一个线程                 * 调用同一个条件上的singalAll方法时为止                 */                sufficientFunds.wait();            }            System.out.println(Thread.currentThread());            accounts[from] -= amount;            System.out.printf("%10.2f from %d to %d ", amount, from, to);            accounts[to] +=amount;            System.out.printf("Total Blance: %10.2f %n", getTotalBalance());            sufficientFunds.signalAll();        } catch (Exception e) {            //e.printStackTrace();        } finally {            /*  临界区抛出异常,但是要把锁释放掉,否则其他线程将永远阻塞。*/            bankLock.unlock();        }    }    public double getTotalBalance() {        bankLock.lock();        try {            double sum = 0;            for ( double a : accounts) {                sum += a;            }            return sum;        } catch (Exception e) {            e.printStackTrace();            return 0.00;        } finally {            bankLock.unlock();        }    }    public int size() {        return accounts.length;    }}
package test2;public class TransferRunnable implements Runnable{    private Bank bank;    private int fromAccount;    private double maxAmount;    private int DELAY = 10;    public TransferRunnable(Bank bank, int fromAccount, double maxAmount) {        this.bank = bank;        this.fromAccount = fromAccount;        this.maxAmount = maxAmount;    }    @Override    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();        }    }}
package test2;public class UnsynchBankTest {    public static final int NACCOUNTS = 100;    public static final double INITIAL_BALANCE = 1000;    public static void main(String[] args) {        Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);        for (int i = 0; i < NACCOUNTS; i++) {            TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);            Thread t = new Thread(r);            t.start();        }    }}
0 0