Java核心技术学习---多线程,锁,同步,条件对象部分应用源码

本文介绍了一个使用Java实现的多线程银行转账系统示例。该示例通过ReentrantLock来确保线程安全,并利用Condition来协调线程间的等待与唤醒。每个线程随机选择转账账户和金额,展示如何在并发环境下进行转账操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bank.java

package testcase;

import java.util.*;
import java.util.concurrent.locks.*;

//考虑同步的多线程编程
public class Bank 
{
	private final double[] accounts;
	private Lock bankLock;
	private Condition sufficientFunds;
	
	
	public Bank(int n,double initialBalance)
	{
		accounts = new double[n];
		Arrays.fill(accounts,initialBalance);
		bankLock = new ReentrantLock(); //构建一个可被用来保护临界区的可重入锁
		sufficientFunds = bankLock.newCondition(); //获得条件对象,一个锁可以有多个条件对象
		
	}
	
	public void transfer(int from,int to,double amount) throws InterruptedException
	{   //用ReentrantLock保护代码块
		bankLock.lock(); //一个ReentrantLock对象 锁对象
		try 
		{
			//若满足以下条件(余额不足),则阻塞当前线程,放弃锁,
			//这样使其他线程可以进行增加余额的操作。
			while(accounts[from] < amount) 
			{ 
				sufficientFunds.await(); //当前线程被阻塞
			}
			System.out.println(Thread.currentThread());
			accounts[from] -=amount;
			System.out.printf("%10.2f from %d to %d",amount,from,to);
			accounts[to] += amount;
			System.out.printf("Total Balance:10.2f%n",getTotalBalance());
			//当另一个线程调用同一条件的signalAll方法时,锁可用且处于阻塞状态的线程才能解除阻塞。
			sufficientFunds.signalAll();//该调用重新激活因为该条件而等待的所有线程
			//signalAll();不会立即激活一个等待线程,仅仅解除等待线程的阻塞,以便这些线程可以在
			//当前线程退出同步方法后,通过竞争实现对对象的访问。
		}
		finally 
		{
			//解锁操作放在finally子句之内至关重要。若临界区代码抛出异常,锁必须被释放,
			//否在其他线程将永远阻塞
			bankLock.unlock(); //解锁操作
		}			
	}
	
	public double getTotalBalance()
	{
		bankLock.lock();
		try
		{
			double sum = 0;
			for(double a :accounts) 
			{
				sum += a;
			}
			return sum;
		}
		finally
		{
			bankLock.unlock();
		}
	}
	
	public int size()
	{
		return accounts.length;
	}
	
	

}

SynBankTest.java

package testcase;

public class SynBankTest {
	public static final int NACCOUNTS = 100;
	public static final double INITIAL_BALANCE = 1000;
	public static final double MAX_AMOUNT = 1000;
	public static final int DELAY = 10;
	
	public static void main(String[] args)
	{
		Bank bank = new Bank(NACCOUNTS,INITIAL_BALANCE);
		for(int i = 0;i < NACCOUNTS; i++)
		{
			int fromAccount = 0;
			Runnable r = ()->{
				try
				{
					while(true)
					{
						int toAccount = (int)(bank.size()*Math.random());
						double amount = MAX_AMOUNT * Math.random();
						bank.transfer(fromAccount, toAccount, amount);
						Thread.sleep((int)(DELAY*Math.random()));
					}
				}catch(InterruptedException e) {}
			};
			
			Thread t = new Thread(r);
			t.start(); //开启线程
		}
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值