Java多线程同步---以银行存取钱的过程的简单代码实例

首先存钱取钱的这个操作,应该是线程操作的,可以有很多的顾客,这意思就是得有多个线程,多个线程之间共同操作一个银行,银行的金额就需要同步。才能保证线程安全。

所以,下面就把这个代码的实例放 这,有不对的地方,还请指出来哈。因为有个老铁问这个多线程的代码。

首先是银行,这个对象model的创建。

package com.lxk.threadTest.bank;

/**
 * 银行model,一个总金额属性。
 * <p>
 *
 * @author lxk on 2017/6/26
 */
public class Bank {
    /**
     * 给银行个启动资金,不然怎么干生意呢。
     */
    private int sum = 200;
    //这个从来不这么用,但也算是正确的一种加锁的机制:同步代码块。
    //Object obj = new Object();

    /**
     * 存钱
     * 要是不加[synchronized--同步函数],则会出现多线程安全问题。
     */
    public synchronized void add(int n) {
        //synchronized (obj) {
        sum = sum + n;
        try {
            Thread.sleep(10);
        } catch (Exception ignore) {
        }
        //当存钱次数变多的时候,就可以发现,存钱的线程确实是2个在交替执行存钱这个动作的。
        System.out.println(Thread.currentThread().getName() + "...sum=" + sum);
        //}
    }

    /**
     * 取钱
     * 要是不加[synchronized--同步函数],则会出现多线程安全问题。
     */
    public synchronized void reduce(int n) {
        if (sum - n >= 0) {
            sum = sum - n;
        } else {
            System.out.println("bank's money is not enough !");
        }
        try {
            Thread.sleep(30);
        } catch (Exception ignore) {
        }
        //当存钱次数变多的时候,就可以发现,存钱的线程确实是2个在交替执行存钱这个动作的。
        System.out.println(Thread.currentThread().getName() + "...sum=" + sum);
    }
}

在代码里面有存和取2个 方法,这2个方法,以及一个总金额,里面有部分被注释掉的代码,那个是简单易懂好理解的,多线程加锁互斥,保证线程间同步的方法。

但是这个是不常用的方法,常用的就是使用synchronized这个关键字来修饰同步方法。

客户对象的model

package com.lxk.threadTest.bank;

/**
 * 顾客,实现runnable()接口,多个人可以一起存钱
 *
 * @author lxk on 2017/6/26
 */
public class Customer implements Runnable {

    /**
     * 存钱类型
     */
    static final String TYPE_ADD = "add";
    /**
     * 取钱类型
     */
    static final String TYPE_REDUCE = "reduce";
    /**
     * 银行
     */
    private Bank bank;
    /**
     * 对钱的操作类型,存钱or取钱
     */
    private String type;
    /**
     * 操作的次数,理论上是个正数
     */
    private int time;
    /**
     * 要存或者取多少钱
     */
    private int money;

    public Customer() {
    }

    public Customer(Bank bank, String type, int time, int money) {
        this.bank = bank;
        this.type = type;
        this.time = time;
        this.money = money;
    }

    @Override
    public void run() {
        for (int x = 0; x < time; x++) {
            if (TYPE_ADD.equals(type)) {
                bank.add(money);
            } else if (TYPE_REDUCE.equals(type)) {
                bank.reduce(money);
            }
        }
    }
}

客户对象,因为可以很多个客户同时访问一个银行,所以,这个存钱取钱的操作就用线程来实现。

属性就构造方法传值了。

main方法

package com.lxk.threadTest.bank;

/**
 * 银行存钱的多线程实例
 * <p>
 * 【需求:】
 * 银行有一个金库。
 * 有两个储户分别存或者取n * 100。
 * 目的:该程序是否有安全问题,如果有,如何解决?
 * <p>
 * 【如何找问题:】
 * 1,明确哪些代码是多线程运行代码。
 * 2,明确共享数据。
 * 3,明确多线程运行代码中哪些语句是操作共享数据的。
 *
 * @author lxk on 2017/6/26
 */
public class Main {
    public static void main(String[] args) {
        //一个银行and多个客户
        Bank bank = new Bank();
        int time = 10000;
        int money = 100;
        //这个客户存钱
        Customer c1 = new Customer(bank, Customer.TYPE_ADD, time, money);
        //这个客户取钱
        Customer c2 = new Customer(bank, Customer.TYPE_REDUCE, time, money);

        Thread t1 = new Thread(c1);
        Thread t2 = new Thread(c2);
        t1.start();
        t2.start();
    }
}

上述代码实际运行效果如下图。

这个存取钱的次数要是小了,就可能会看到2个线程有先后顺序,所以,这个次数咱整多点,然后,就看到如图所示的情况,线程1是取钱的,线程0时存钱的,可以看到2个线程是互相交错执行的,有存有取,没有规律可言。

这个就保证了数据的同步了。

至于如何才能不同步,也就是异常的现象,

你可以把add方法的这个synchronized 关键字去掉之后,把次数调小一点改成3次,sum的初始值给设置成0.你再试试代码,

就会发现所谓的不同步现象。

上图的右边就是不同步的结果,2个人每次存100,存三次,总数是不是得,100,200,300,400,500,600.得长。

但是,运行结果却不是的,

这个时候,你再把synchronized给add方法加上去,就会出现左边的图的结果,这个就是正确的结果。

我是为了,有存有取,所以,就又加了个方法。代码就变成上面的样子啦。

差不多都是线程间同步的例子啦。

 

我就简单记录下代码。用的时候,可以分分钟就拿出来。

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值