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
共同学习,写下你的评论
评论加载中...
作者其他优质文章