问题:开户为10000,其中张三隔一段时间会存入100,李四会隔一段时间进行取款100,王五会过一段时间取款200,存入金额不能超过20000,当取款为0时,进行,如何保障该阶段的数据一致性问题
解决方案:将开户金额设置为atomic原子类,同时取款贷款设置为synchronized即可解决该问题

开户类Account

package com.currency.currency05;import lombok.Data;import java.util.concurrent.atomic.AtomicInteger;@Datapublic class Account {    private String name;    private AtomicInteger amount;    public void name() {        System.out.println("账户为:" + name + "!");    }    public synchronized boolean deposit(String threadName, Integer change) {        amount.addAndGet(change);        if(amount.get() > 20000) {            System.out.print("贷款金额曾经达到下限,贷款失败");            return false;        }        System.out.println("01:" + threadName+",贷款金额为"+change + ",开始贷款,贷款后余额为" + amount);        return true;    }    public synchronized  boolean withdraw(String threadName, Integer money) {        if (amount.get() <= 0 || amount.get() < money) {            System.out.println(threadName+",账户金额为"+amount.get()+",你的取款金额为"+money+",取款失败");            return false;        } else {            amount.addAndGet(-money);            System.out.println("02:" + threadName+",取款金额为"+money + ",开始取款,取款后余额为" + amount);            return true;        }    }    public synchronized void openAccount(String name, Integer money) {        this.name = name;        this.amount = new AtomicInteger(money);        System.out.println("00:" + name + "开户胜利,开户金额为"+money);    }}

取款类Deposit

package com.currency.currency05;import lombok.Data;import java.util.Random;@Datapublic class Deposit implements Runnable{    private Account account;    private int deposit;    public void deposit(Account account, int deposit) {        this.account = account;        this.deposit = deposit;    }    @Override    public void run() {        String threadName = Thread.currentThread().getName();        while (true) {            if (account.getAmount().get() < 20000) {                boolean isFlag = account.deposit(threadName, deposit);                if (!isFlag) {                    break;                }                try {                    Thread.sleep(new Random().nextInt(1000));                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            if (account.getAmount().get() >= 20000) {                break;            }            if (account.getAmount().get() == 0) {                System.out.println("余额为零,贷款完结");                break;            }        }    }}

贷款类Withdraw

package com.currency.currency05;import java.util.Random;/** * @author huanglaoxie(微信:yfct-8888) * @className Withdraw * @description: * @date 2017/12/20 10:16 */public class Withdraw implements Runnable{    private Account account;    private int withdraw;    public void withdraw(Account account, int withdraw) {        this.account = account;        this.withdraw = withdraw;    }    @Override    public void run() {        String threadName = Thread.currentThread().getName();        while (true) {            if (account.getAmount().get() > 0) {                boolean isFlag = account.withdraw(threadName, withdraw);                if (!isFlag) {                    break;                }                try {                    Thread.sleep(new Random().nextInt(1000));                } catch (InterruptedException e) {                    e.printStackTrace();                }            } else {                break;            }        }    }}

线程执行

package com.currency.currency05;public class Test {    public static void main(String[] args) {        Account account = new Account();        account.openAccount("zhouzhou", 10000);        Deposit p1 = new Deposit();        p1.deposit(account, 100);        Thread depositThread = new Thread(p1, "张三");        Withdraw p2 = new Withdraw();        p2.withdraw(account, 100);        Thread withdrawThread1 = new Thread(p2, "李四");        Withdraw p3 = new Withdraw();        p3.withdraw(account, 200);        Thread withdrawThread2 = new Thread(p3, "王五");        withdrawThread1.start();        withdrawThread2.start();        depositThread.start();    }}

测试后果

/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/bin/java -Dvisualvm.id=220271645666 -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=49342:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/legacy8ujsse.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/openjsse.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/lib/tools.jar:/Users/suyuzhou/Downloads/currency05/target/classes:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/boot/spring-boot-starter/2.5.5/spring-boot-starter-2.5.5.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/boot/spring-boot/2.5.5/spring-boot-2.5.5.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/spring-context/5.3.10/spring-context-5.3.10.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/spring-aop/5.3.10/spring-aop-5.3.10.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/spring-beans/5.3.10/spring-beans-5.3.10.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/spring-expression/5.3.10/spring-expression-5.3.10.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/boot/spring-boot-autoconfigure/2.5.5/spring-boot-autoconfigure-2.5.5.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/boot/spring-boot-starter-logging/2.5.5/spring-boot-starter-logging-2.5.5.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/ch/qos/logback/logback-classic/1.2.6/logback-classic-1.2.6.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/ch/qos/logback/logback-core/1.2.6/logback-core-1.2.6.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/apache/logging/log4j/log4j-to-slf4j/2.14.1/log4j-to-slf4j-2.14.1.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/apache/logging/log4j/log4j-api/2.14.1/log4j-api-2.14.1.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/slf4j/jul-to-slf4j/1.7.32/jul-to-slf4j-1.7.32.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/spring-core/5.3.10/spring-core-5.3.10.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/springframework/spring-jcl/5.3.10/spring-jcl-5.3.10.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/yaml/snakeyaml/1.28/snakeyaml-1.28.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/projectlombok/lombok/1.18.20/lombok-1.18.20.jar:/Users/suyuzhou/coding/maven/apache-maven-3.8.1/localRepository/org/slf4j/slf4j-api/1.7.32/slf4j-api-1.7.32.jar com.currency.currency05.Test00:zhouzhou开户胜利,开户金额为1000002:李四,取款金额为100,开始取款,取款后余额为990001:张三,贷款金额为100,开始贷款,贷款后余额为1000002:王五,取款金额为200,开始取款,取款后余额为980002:王五,取款金额为200,开始取款,取款后余额为960001:张三,贷款金额为100,开始贷款,贷款后余额为970002:李四,取款金额为100,开始取款,取款后余额为960002:王五,取款金额为200,开始取款,取款后余额为940001:张三,贷款金额为100,开始贷款,贷款后余额为950001:张三,贷款金额为100,开始贷款,贷款后余额为960002:王五,取款金额为200,开始取款,取款后余额为940002:王五,取款金额为200,开始取款,取款后余额为920002:李四,取款金额为100,开始取款,取款后余额为910002:王五,取款金额为200,开始取款,取款后余额为890001:张三,贷款金额为100,开始贷款,贷款后余额为900002:李四,取款金额为100,开始取款,取款后余额为890002:王五,取款金额为200,开始取款,取款后余额为870002:李四,取款金额为100,开始取款,取款后余额为860002:李四,取款金额为100,开始取款,取款后余额为850002:王五,取款金额为200,开始取款,取款后余额为830001:张三,贷款金额为100,开始贷款,贷款后余额为840002:李四,取款金额为100,开始取款,取款后余额为830002:李四,取款金额为100,开始取款,取款后余额为820002:王五,取款金额为200,开始取款,取款后余额为800001:张三,贷款金额为100,开始贷款,贷款后余额为810002:李四,取款金额为100,开始取款,取款后余额为800001:张三,贷款金额为100,开始贷款,贷款后余额为810002:王五,取款金额为200,开始取款,取款后余额为790002:李四,取款金额为100,开始取款,取款后余额为780001:张三,贷款金额为100,开始贷款,贷款后余额为790002:王五,取款金额为200,开始取款,取款后余额为770001:张三,贷款金额为100,开始贷款,贷款后余额为780002:李四,取款金额为100,开始取款,取款后余额为770001:张三,贷款金额为100,开始贷款,贷款后余额为780002:李四,取款金额为100,开始取款,取款后余额为770002:李四,取款金额为100,开始取款,取款后余额为760001:张三,贷款金额为100,开始贷款,贷款后余额为770002:王五,取款金额为200,开始取款,取款后余额为750002:李四,取款金额为100,开始取款,取款后余额为740002:李四,取款金额为100,开始取款,取款后余额为730001:张三,贷款金额为100,开始贷款,贷款后余额为740001:张三,贷款金额为100,开始贷款,贷款后余额为750002:李四,取款金额为100,开始取款,取款后余额为740002:王五,取款金额为200,开始取款,取款后余额为720002:王五,取款金额为200,开始取款,取款后余额为700002:王五,取款金额为200,开始取款,取款后余额为680001:张三,贷款金额为100,开始贷款,贷款后余额为690002:李四,取款金额为100,开始取款,取款后余额为680002:王五,取款金额为200,开始取款,取款后余额为660001:张三,贷款金额为100,开始贷款,贷款后余额为670002:王五,取款金额为200,开始取款,取款后余额为650002:李四,取款金额为100,开始取款,取款后余额为640001:张三,贷款金额为100,开始贷款,贷款后余额为650001:张三,贷款金额为100,开始贷款,贷款后余额为660002:李四,取款金额为100,开始取款,取款后余额为650001:张三,贷款金额为100,开始贷款,贷款后余额为660002:王五,取款金额为200,开始取款,取款后余额为640002:李四,取款金额为100,开始取款,取款后余额为630001:张三,贷款金额为100,开始贷款,贷款后余额为640001:张三,贷款金额为100,开始贷款,贷款后余额为650002:李四,取款金额为100,开始取款,取款后余额为640002:王五,取款金额为200,开始取款,取款后余额为620002:李四,取款金额为100,开始取款,取款后余额为610002:李四,取款金额为100,开始取款,取款后余额为600001:张三,贷款金额为100,开始贷款,贷款后余额为610002:王五,取款金额为200,开始取款,取款后余额为590002:王五,取款金额为200,开始取款,取款后余额为570002:李四,取款金额为100,开始取款,取款后余额为560001:张三,贷款金额为100,开始贷款,贷款后余额为570002:李四,取款金额为100,开始取款,取款后余额为560002:王五,取款金额为200,开始取款,取款后余额为540001:张三,贷款金额为100,开始贷款,贷款后余额为550001:张三,贷款金额为100,开始贷款,贷款后余额为560002:王五,取款金额为200,开始取款,取款后余额为540002:王五,取款金额为200,开始取款,取款后余额为520002:李四,取款金额为100,开始取款,取款后余额为510002:李四,取款金额为100,开始取款,取款后余额为500001:张三,贷款金额为100,开始贷款,贷款后余额为510002:王五,取款金额为200,开始取款,取款后余额为490002:李四,取款金额为100,开始取款,取款后余额为480002:王五,取款金额为200,开始取款,取款后余额为460001:张三,贷款金额为100,开始贷款,贷款后余额为470002:李四,取款金额为100,开始取款,取款后余额为460002:王五,取款金额为200,开始取款,取款后余额为440002:李四,取款金额为100,开始取款,取款后余额为430001:张三,贷款金额为100,开始贷款,贷款后余额为440001:张三,贷款金额为100,开始贷款,贷款后余额为450002:王五,取款金额为200,开始取款,取款后余额为430002:李四,取款金额为100,开始取款,取款后余额为420002:王五,取款金额为200,开始取款,取款后余额为400002:李四,取款金额为100,开始取款,取款后余额为390002:李四,取款金额为100,开始取款,取款后余额为380001:张三,贷款金额为100,开始贷款,贷款后余额为390001:张三,贷款金额为100,开始贷款,贷款后余额为400002:王五,取款金额为200,开始取款,取款后余额为380001:张三,贷款金额为100,开始贷款,贷款后余额为390002:李四,取款金额为100,开始取款,取款后余额为380002:王五,取款金额为200,开始取款,取款后余额为360002:李四,取款金额为100,开始取款,取款后余额为350002:王五,取款金额为200,开始取款,取款后余额为330002:王五,取款金额为200,开始取款,取款后余额为310002:李四,取款金额为100,开始取款,取款后余额为300001:张三,贷款金额为100,开始贷款,贷款后余额为310002:李四,取款金额为100,开始取款,取款后余额为300002:王五,取款金额为200,开始取款,取款后余额为280001:张三,贷款金额为100,开始贷款,贷款后余额为290001:张三,贷款金额为100,开始贷款,贷款后余额为300001:张三,贷款金额为100,开始贷款,贷款后余额为310002:王五,取款金额为200,开始取款,取款后余额为290002:李四,取款金额为100,开始取款,取款后余额为280002:王五,取款金额为200,开始取款,取款后余额为260001:张三,贷款金额为100,开始贷款,贷款后余额为270001:张三,贷款金额为100,开始贷款,贷款后余额为280001:张三,贷款金额为100,开始贷款,贷款后余额为290002:李四,取款金额为100,开始取款,取款后余额为280001:张三,贷款金额为100,开始贷款,贷款后余额为290002:王五,取款金额为200,开始取款,取款后余额为270001:张三,贷款金额为100,开始贷款,贷款后余额为280002:李四,取款金额为100,开始取款,取款后余额为270002:王五,取款金额为200,开始取款,取款后余额为250001:张三,贷款金额为100,开始贷款,贷款后余额为260002:王五,取款金额为200,开始取款,取款后余额为240002:王五,取款金额为200,开始取款,取款后余额为220002:李四,取款金额为100,开始取款,取款后余额为210002:李四,取款金额为100,开始取款,取款后余额为200002:王五,取款金额为200,开始取款,取款后余额为180001:张三,贷款金额为100,开始贷款,贷款后余额为190002:李四,取款金额为100,开始取款,取款后余额为180002:王五,取款金额为200,开始取款,取款后余额为160001:张三,贷款金额为100,开始贷款,贷款后余额为170001:张三,贷款金额为100,开始贷款,贷款后余额为180002:王五,取款金额为200,开始取款,取款后余额为160002:李四,取款金额为100,开始取款,取款后余额为150001:张三,贷款金额为100,开始贷款,贷款后余额为160002:王五,取款金额为200,开始取款,取款后余额为140001:张三,贷款金额为100,开始贷款,贷款后余额为150002:王五,取款金额为200,开始取款,取款后余额为130002:王五,取款金额为200,开始取款,取款后余额为110001:张三,贷款金额为100,开始贷款,贷款后余额为120002:李四,取款金额为100,开始取款,取款后余额为110002:王五,取款金额为200,开始取款,取款后余额为90002:王五,取款金额为200,开始取款,取款后余额为70001:张三,贷款金额为100,开始贷款,贷款后余额为80002:李四,取款金额为100,开始取款,取款后余额为70002:王五,取款金额为200,开始取款,取款后余额为50001:张三,贷款金额为100,开始贷款,贷款后余额为60002:李四,取款金额为100,开始取款,取款后余额为50002:王五,取款金额为200,开始取款,取款后余额为30002:李四,取款金额为100,开始取款,取款后余额为20001:张三,贷款金额为100,开始贷款,贷款后余额为30002:李四,取款金额为100,开始取款,取款后余额为20002:王五,取款金额为200,开始取款,取款后余额为0余额为零,贷款完结Process finished with exit code 0