package com.chengxi.multithread.transfermoney;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* @Author: CHENGXI
*/
public class MyTransfer {
public static void main(String[] args) {
Account src = new Account(10000);
Account target = new Account(10000);
CountDownLatch countDownLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
src.transactionToTarget(1, target);
countDownLatch.countDown();
}).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("src = " + src.getBalance());
System.out.println("target = " + target.getBalance());
}
}
// 单例的资源管理对象
class Allocator {
private Allocator() {}
public static Allocator getInstance() {
return InnerAllocator.instance;
}
static class InnerAllocator {
private static final Allocator instance = new Allocator();
}
private List<Account> locks = new ArrayList<>();
// 一次申请所有资源
public synchronized void apply(Account src, Account tag) {
System.out.println(Thread.currentThread().getName() + " 拿到获取资源的锁");
while (locks.contains(src) || locks.contains(tag)) {
try {
System.out.println(Thread.currentThread().getName() + " 条件队列已有资源, 开始等待");
this.wait();
System.out.println(Thread.currentThread().getName() + " 已被唤醒并拿到锁, 继续执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + " 往条件队列里面添加资源");
locks.add(src);
locks.add(tag);
System.out.println(Thread.currentThread().getName() + " 资源添加完成");
System.out.println();
}
// 归还所有资源
public synchronized void release(Account src, Account tag) {
System.out.println(Thread.currentThread().getName() + " 转账完成, 释放资源, 并唤醒所有线程");
locks.remove(src);
locks.remove(tag);
this.notifyAll();
System.out.println();
}
}
class Account {
private Integer balance;
public Account(Integer balance) {
this.balance = balance;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
// 转账方法
public void transactionToTarget(Integer money, Account target) {
System.out.println(Thread.currentThread().getName() + " 尝试获取Allocator单例");
Allocator.getInstance().apply(this, target);
System.out.println(Thread.currentThread().getName() + " 获取到单例对象和资源, 开始转账");
this.balance -= money;
target.setBalance(target.getBalance() + money);
Allocator.getInstance().release(this, target);
}
}输出结果:
Thread-0 尝试获取Allocator单例
Thread-3 尝试获取Allocator单例
Thread-1 尝试获取Allocator单例
Thread-2 尝试获取Allocator单例
Thread-4 尝试获取Allocator单例
Thread-2 拿到获取资源的锁
Thread[Thread-2,5,main] 往条件队列里面添加资源
Thread-2 资源添加完成
Thread-2 获取到单例对象和资源, 开始转账
Thread-0 拿到获取资源的锁
Thread-0 条件队列已有资源, 开始等待
Thread-3 拿到获取资源的锁
Thread-3 条件队列已有资源, 开始等待
Thread-1 拿到获取资源的锁
Thread-1 条件队列已有资源, 开始等待
Thread-4 拿到获取资源的锁
Thread-4 条件队列已有资源, 开始等待
Thread-2 转账完成, 释放资源, 并唤醒所有线程
Thread-4 已被唤醒并拿到锁, 继续执行
Thread[Thread-4,5,main] 往条件队列里面添加资源
Thread-4 资源添加完成
Thread-4 获取到单例对象和资源, 开始转账
Thread-1 已被唤醒并拿到锁, 继续执行
Thread-1 条件队列已有资源, 开始等待
Thread-3 已被唤醒并拿到锁, 继续执行
Thread-3 条件队列已有资源, 开始等待
Thread-0 已被唤醒并拿到锁, 继续执行
Thread-0 条件队列已有资源, 开始等待
Thread-4 转账完成, 释放资源, 并唤醒所有线程
Thread-0 已被唤醒并拿到锁, 继续执行
Thread[Thread-0,5,main] 往条件队列里面添加资源
Thread-0 资源添加完成
Thread-0 获取到单例对象和资源, 开始转账
Thread-3 已被唤醒并拿到锁, 继续执行
Thread-3 条件队列已有资源, 开始等待
Thread-1 已被唤醒并拿到锁, 继续执行
Thread-1 条件队列已有资源, 开始等待
Thread-0 转账完成, 释放资源, 并唤醒所有线程
Thread-1 已被唤醒并拿到锁, 继续执行
Thread[Thread-1,5,main] 往条件队列里面添加资源
Thread-1 资源添加完成
Thread-1 获取到单例对象和资源, 开始转账
Thread-3 已被唤醒并拿到锁, 继续执行
Thread-3 条件队列已有资源, 开始等待
Thread-1 转账完成, 释放资源, 并唤醒所有线程
Thread-3 已被唤醒并拿到锁, 继续执行
Thread[Thread-3,5,main] 往条件队列里面添加资源
Thread-3 资源添加完成
Thread-3 获取到单例对象和资源, 开始转账
Thread-3 转账完成, 释放资源, 并唤醒所有线程
src = 9995
target = 10005