java多线程:向银行账户存钱

问题描述:100个线程同时向一个银行账户存入1元钱。

1:使用同步机制

银行账户类:

/**
 * 银行账户类
 * 演示100个线程同时向一个银行账户存入1元钱
 * 未使用同步机制
 */
public class Account {
    // 账户余额
    private double balance;

    /**
     * 存款
     * @param money : 存入金额
     */
    public synchronized void deposit(double money) {
        double newBalance = balance + money;
        try {
            Thread.sleep(10);   // 模拟此业务需要一段处理时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        balance = newBalance;
    }

    /**
     * 获得账户余额
     * @return : 账户余额
     */
    public double getBalance() {
        return balance;
    }
}

存钱线程:

/**
 * 存钱线程
 */
public class AddMoneyThread implements Runnable{

    // 存入账户
    // 方法一
      private Account account;
    // 方法二
//    private Account02 account;

    // 存入金额
    private double money;

    public AddMoneyThread(Account account, double money) {
        this.account = account;
        this.money = money;
    }

    @Override
    public void run() {
        synchronized (account) {
            account.deposit(money);
        }
    }
}

测试类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test01 {

    public static void main(String[] args) {
        // 方式一
        Account account =  new Account();
        // 方式二
//        Account02 account = new Account02();
        // 创建线程池
        ExecutorService service = Executors.newFixedThreadPool(100);
        for (int i=1;i<=100;i++) {
            /**
             * execute():方法接收一个Runnable实例,并且异步执行
             */
            service.execute(new AddMoneyThread(account,1));
        }
        /**
         * 当线程池调用该方法时,线程池的状态则立刻变成shutdown状态。此时,则不能在往线程池中添加任何任务,否则将会抛出异常。
         * 但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。
         */
        service.shutdown();
        /**
         * isTerminated():当调用shutdown()方法后,并且当所有提交的任务完成后返回true;
         */
        while (!service.isTerminated()) {
            System.out.println("账户余额: "+account.getBalance());
        }
    }
}

2:通过ReentrantLock()

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 为每个银行账户创建一个锁对象,在存款操作进行加锁和解锁的操作
 */
public class Account02 {
    /**
     * ReentrantLock是可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞而被放入该锁的AQS阻塞队列里面
     *
     */
    private Lock accountLock = new ReentrantLock();
    private double balance;

    // 存款
    public void deposit(double money) {
        /**
         * 尝试获取锁
         */
        accountLock.lock();
        try {
            double newBalance = balance + money;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            balance = newBalance;
        } finally {
            /**
             * 尝试释放锁,如果当前线程持有该锁,则调用该方法会让线程对该线程持有的AQS状态值减一,如果减去1后当前状态值为0
             * 则当前线程会释放该锁,否则仅仅减一而已。如果当前线程没有持有该锁而调用了该方法会抛出异常
             */
            accountLock.unlock();
        }
    }

    // 获得账户余额
    public double getBalance() {
        return balance;
    }
}

 

你可能感兴趣的:(java,多线程)