问题:开户为 10000,其中张三隔一段时间会存入 100,李四会隔一段时间进行取款 100,王五会过一段时间取款 200,存入金额不能超过 20000,当取款为 0 时,进行,如何保障该阶段的数据一致性问题
解决方案:将开户金额设置为 atomic 原子类,同时取款贷款设置为 synchronized 即可解决该问题
开户类 Account
package com.currency.currency05;
import lombok.Data;
import java.util.concurrent.atomic.AtomicInteger;
@Data
public 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;
@Data
public 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.Test
00:zhouzhou 开户胜利, 开户金额为 10000
02:李四, 取款金额为 100, 开始取款,取款后余额为 9900
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 10000
02:王五, 取款金额为 200, 开始取款,取款后余额为 9800
02:王五, 取款金额为 200, 开始取款,取款后余额为 9600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 9700
02:李四, 取款金额为 100, 开始取款,取款后余额为 9600
02:王五, 取款金额为 200, 开始取款,取款后余额为 9400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 9500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 9600
02:王五, 取款金额为 200, 开始取款,取款后余额为 9400
02:王五, 取款金额为 200, 开始取款,取款后余额为 9200
02:李四, 取款金额为 100, 开始取款,取款后余额为 9100
02:王五, 取款金额为 200, 开始取款,取款后余额为 8900
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 9000
02:李四, 取款金额为 100, 开始取款,取款后余额为 8900
02:王五, 取款金额为 200, 开始取款,取款后余额为 8700
02:李四, 取款金额为 100, 开始取款,取款后余额为 8600
02:李四, 取款金额为 100, 开始取款,取款后余额为 8500
02:王五, 取款金额为 200, 开始取款,取款后余额为 8300
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 8400
02:李四, 取款金额为 100, 开始取款,取款后余额为 8300
02:李四, 取款金额为 100, 开始取款,取款后余额为 8200
02:王五, 取款金额为 200, 开始取款,取款后余额为 8000
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 8100
02:李四, 取款金额为 100, 开始取款,取款后余额为 8000
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 8100
02:王五, 取款金额为 200, 开始取款,取款后余额为 7900
02:李四, 取款金额为 100, 开始取款,取款后余额为 7800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 7900
02:王五, 取款金额为 200, 开始取款,取款后余额为 7700
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 7800
02:李四, 取款金额为 100, 开始取款,取款后余额为 7700
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 7800
02:李四, 取款金额为 100, 开始取款,取款后余额为 7700
02:李四, 取款金额为 100, 开始取款,取款后余额为 7600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 7700
02:王五, 取款金额为 200, 开始取款,取款后余额为 7500
02:李四, 取款金额为 100, 开始取款,取款后余额为 7400
02:李四, 取款金额为 100, 开始取款,取款后余额为 7300
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 7400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 7500
02:李四, 取款金额为 100, 开始取款,取款后余额为 7400
02:王五, 取款金额为 200, 开始取款,取款后余额为 7200
02:王五, 取款金额为 200, 开始取款,取款后余额为 7000
02:王五, 取款金额为 200, 开始取款,取款后余额为 6800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6900
02:李四, 取款金额为 100, 开始取款,取款后余额为 6800
02:王五, 取款金额为 200, 开始取款,取款后余额为 6600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6700
02:王五, 取款金额为 200, 开始取款,取款后余额为 6500
02:李四, 取款金额为 100, 开始取款,取款后余额为 6400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6600
02:李四, 取款金额为 100, 开始取款,取款后余额为 6500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6600
02:王五, 取款金额为 200, 开始取款,取款后余额为 6400
02:李四, 取款金额为 100, 开始取款,取款后余额为 6300
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6500
02:李四, 取款金额为 100, 开始取款,取款后余额为 6400
02:王五, 取款金额为 200, 开始取款,取款后余额为 6200
02:李四, 取款金额为 100, 开始取款,取款后余额为 6100
02:李四, 取款金额为 100, 开始取款,取款后余额为 6000
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 6100
02:王五, 取款金额为 200, 开始取款,取款后余额为 5900
02:王五, 取款金额为 200, 开始取款,取款后余额为 5700
02:李四, 取款金额为 100, 开始取款,取款后余额为 5600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 5700
02:李四, 取款金额为 100, 开始取款,取款后余额为 5600
02:王五, 取款金额为 200, 开始取款,取款后余额为 5400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 5500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 5600
02:王五, 取款金额为 200, 开始取款,取款后余额为 5400
02:王五, 取款金额为 200, 开始取款,取款后余额为 5200
02:李四, 取款金额为 100, 开始取款,取款后余额为 5100
02:李四, 取款金额为 100, 开始取款,取款后余额为 5000
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 5100
02:王五, 取款金额为 200, 开始取款,取款后余额为 4900
02:李四, 取款金额为 100, 开始取款,取款后余额为 4800
02:王五, 取款金额为 200, 开始取款,取款后余额为 4600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 4700
02:李四, 取款金额为 100, 开始取款,取款后余额为 4600
02:王五, 取款金额为 200, 开始取款,取款后余额为 4400
02:李四, 取款金额为 100, 开始取款,取款后余额为 4300
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 4400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 4500
02:王五, 取款金额为 200, 开始取款,取款后余额为 4300
02:李四, 取款金额为 100, 开始取款,取款后余额为 4200
02:王五, 取款金额为 200, 开始取款,取款后余额为 4000
02:李四, 取款金额为 100, 开始取款,取款后余额为 3900
02:李四, 取款金额为 100, 开始取款,取款后余额为 3800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 3900
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 4000
02:王五, 取款金额为 200, 开始取款,取款后余额为 3800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 3900
02:李四, 取款金额为 100, 开始取款,取款后余额为 3800
02:王五, 取款金额为 200, 开始取款,取款后余额为 3600
02:李四, 取款金额为 100, 开始取款,取款后余额为 3500
02:王五, 取款金额为 200, 开始取款,取款后余额为 3300
02:王五, 取款金额为 200, 开始取款,取款后余额为 3100
02:李四, 取款金额为 100, 开始取款,取款后余额为 3000
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 3100
02:李四, 取款金额为 100, 开始取款,取款后余额为 3000
02:王五, 取款金额为 200, 开始取款,取款后余额为 2800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2900
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 3000
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 3100
02:王五, 取款金额为 200, 开始取款,取款后余额为 2900
02:李四, 取款金额为 100, 开始取款,取款后余额为 2800
02:王五, 取款金额为 200, 开始取款,取款后余额为 2600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2700
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2900
02:李四, 取款金额为 100, 开始取款,取款后余额为 2800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2900
02:王五, 取款金额为 200, 开始取款,取款后余额为 2700
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2800
02:李四, 取款金额为 100, 开始取款,取款后余额为 2700
02:王五, 取款金额为 200, 开始取款,取款后余额为 2500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 2600
02:王五, 取款金额为 200, 开始取款,取款后余额为 2400
02:王五, 取款金额为 200, 开始取款,取款后余额为 2200
02:李四, 取款金额为 100, 开始取款,取款后余额为 2100
02:李四, 取款金额为 100, 开始取款,取款后余额为 2000
02:王五, 取款金额为 200, 开始取款,取款后余额为 1800
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 1900
02:李四, 取款金额为 100, 开始取款,取款后余额为 1800
02:王五, 取款金额为 200, 开始取款,取款后余额为 1600
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 1700
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 1800
02:王五, 取款金额为 200, 开始取款,取款后余额为 1600
02:李四, 取款金额为 100, 开始取款,取款后余额为 1500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 1600
02:王五, 取款金额为 200, 开始取款,取款后余额为 1400
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 1500
02:王五, 取款金额为 200, 开始取款,取款后余额为 1300
02:王五, 取款金额为 200, 开始取款,取款后余额为 1100
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 1200
02:李四, 取款金额为 100, 开始取款,取款后余额为 1100
02:王五, 取款金额为 200, 开始取款,取款后余额为 900
02:王五, 取款金额为 200, 开始取款,取款后余额为 700
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 800
02:李四, 取款金额为 100, 开始取款,取款后余额为 700
02:王五, 取款金额为 200, 开始取款,取款后余额为 500
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 600
02:李四, 取款金额为 100, 开始取款,取款后余额为 500
02:王五, 取款金额为 200, 开始取款,取款后余额为 300
02:李四, 取款金额为 100, 开始取款,取款后余额为 200
01:张三, 贷款金额为 100, 开始贷款,贷款后余额为 300
02:李四, 取款金额为 100, 开始取款,取款后余额为 200
02:王五, 取款金额为 200, 开始取款,取款后余额为 0
余额为零,贷款完结
Process finished with exit code 0