Java核心技術學習---多線程,鎖,同步,條件對象部分應用源碼

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(); //開啓線程
		}
	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章