首先来看线程不安全的转账
public class Bank {
private int[] accounts;
public Bank() {
this.accounts = new int[10];
for (int i = 0; i < 10; i++) {
accounts[i] = 1000;
}
}
public void transfer(int from, int to, int amount) {
if (accounts[from] >= amount) {
accounts[from] -= amount;
accounts[to] += amount;
}
}
public int total() {
int count = 0;
for (int i = 0; i < 10; i++) {
count += accounts[i];
}
return count;
}
}
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
Bank bank = new Bank();
Random random = new Random();
CountDownLatch countDownLatch = new CountDownLatch(10000);
for (int i = 0; i < 10000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int from = random.nextInt(10);
int to = random.nextInt(10);
int amount = random.nextInt(1000);
bank.transfer(from, to, amount);
System.out.println(Thread.currentThread().getName() + " 从 " + from + " 转账到 " + to + " " + amount + " 元");
countDownLatch.countDown();
}
}).start();
}
try {
countDownLatch.await();
System.out.println("银行最终总余额 = " + bank.total());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
线程安全的转账
竞争太激烈,所有线程都在抢同一把银行锁
public class Bank {
private int[] accounts;
public Bank() {
this.accounts = new int[10];
for (int i = 0; i < 10; i++) {
accounts[i] = 1000;
}
}
public synchronized void transfer(int from, int to, int amount) {
if (accounts[from] >= amount) {
accounts[from] -= amount;
accounts[to] += amount;
}
}
public int total() {
int count = 0;
for (int i = 0; i < 10; i++) {
count += accounts[i];
}
return count;
}
}
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
Bank bank = new Bank();
Random random = new Random();
CountDownLatch countDownLatch = new CountDownLatch(10000);
for (int i = 0; i < 10000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int from = random.nextInt(10);
int to = random.nextInt(10);
int amount = random.nextInt(1000);
bank.transfer(from, to, amount);
System.out.println(Thread.currentThread().getName() + " 从 " + from + " 转账到 " + to + " " + amount + " 元");
countDownLatch.countDown();
}
}).start();
}
try {
countDownLatch.await();
System.out.println("银行最终总余额 = " + bank.total());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
线程安全的转账升级版
分散锁到各个账户上去,每个线程只要取得两个账户上的锁即可,
要注意按顺序获取锁,否则会死锁
import java.util.concurrent.locks.ReentrantLock;
public class Account {
private int money;
private ReentrantLock lock;
public Account(int money){
this.money = money;
lock = new ReentrantLock();
}
public ReentrantLock getLock() {
return lock;
}
public int getMoney() {
return money;
}
public void sub(int money){
this.money -= money;
}
public void add(int money){
this.money += money;
}
}
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
public class Bank {
private Account[] accounts;
public Bank(int num){
this.accounts = new Account[1000];
for(int i = 0;i<num;i++){
this.accounts[i] = new Account(1000);
}
}
public void transfer(int from ,int to ,int amount){
ReentrantLock lock1,lock2;
if (from < to){
lock1 = accounts[from].getLock();
lock2 = accounts[to].getLock();
}else if(from > to){
lock2 = accounts[from].getLock();
lock1 = accounts[to].getLock();
}else{
return;
}
synchronized (lock1){
synchronized (lock2){
if(accounts[from].getMoney()>=amount){
accounts[from].sub(amount);
accounts[to].add(amount);
}
}
}
}
public int total(){
int count = 0;
for (int i = 0;i<this.accounts.length ;i++){
count += accounts[i].getMoney();
}
return count;
}
}
import java.sql.Time;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
Bank bank = new Bank(1000);
Random random = new Random();
CountDownLatch countDownLatch = new CountDownLatch(1000);
long start = System.nanoTime();
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int from = random.nextInt(10);
int to = random.nextInt(10);
int amount = random.nextInt(1000);
bank.transfer(from, to, amount);
System.out.println(Thread.currentThread().getName() + " 从 " + from + " 转账到 " + to + " " + amount + " 元");
countDownLatch.countDown();
}
}).start();
}
try {
countDownLatch.await();
long end = System.nanoTime();
System.out.println("程序运行总时间 "+ (end - start)/1000000 + "毫秒");
System.out.println("银行最终总余额 = " + bank.total());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
标签:转账,Java,int,random,amount,线程,accounts,new,public
From: https://www.cnblogs.com/DCFV/p/18374525