Java語言內置了synchronized關鍵字用於對多線程進行同步,大大方便了Java中多線程程序的編寫。但是僅僅使用synchronized關鍵字還不能滿足對多線程進行同步的所有需要。大家知道,synchronized僅僅能夠對方法或者代碼塊進行同步,如果我們一個應用需要跨越多個方法進行同步,synchroinzed就不能勝任了。在C++中有很多同步機制,比如信號量、互斥體、臨屆區等。在Java中也可以在synchronized語言特性的基礎上,在更高層次構建這樣的同步工具,以方便我們的使用。
當前,廣為使用的是由Doug Lea編寫的一個Java中同步的工具包,可以在這兒了解更多這個包的詳細情況:
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.Html
該工具包已經作為JSR166正處於JCP的控制下,即將作為JDK1.5的正式組成部分。本文並不打算詳細剖析這個工具包,而是對多種同步機制的一個介紹,同時給出這類同步機制的實例實現,這並不是工業級的實現。但其中會參考Doug Lea的這個同步包中的工業級實現的一些代碼片斷。
本例中還沿用上篇中的Account類,不過我們這兒編寫一個新的ATM類來模擬自動提款機,通過一個ATMTester的類,生成10個ATM線程,同時對John賬戶進行查詢、提款和存款操作。Account類做了一些改動,以便適應本篇的需要:
import Java.util.HashMap;
import Java.util.Map;
class Account
{
String name;
//float amount;
//使用一個Map模擬持久存儲
static Map storage = new HashMap();
static
{
storage.put("John", new Float(1000.0f));
storage.put("Mike", new Float(800.0f));
}
public Account(String name)
{
//System.out.println("new account:" + name);
this.name = name;
//this.amount = ((Float)storage.get(name)).floatValue();
}
public synchronized void deposit(float amt)
{
float amount = ((Float)storage.get(name)).floatValue();
storage.put(name, new Float(amount + amt));
}
public synchronized void withdraw(float amt)
throws InsufficIEntBalanceException
{
float amount = ((Float)storage.get(name)).floatValue();
if (amount >= amt) amount -= amt;
else throw new InsufficIEntBalanceException();
storage.put(name, new Float(amount));
}
public float getBalance()
{
float amount = ((Float)storage.get(name)).floatValue();
return amount;
}
}
在新的Account類中,我們采用一個HashMap來存儲賬戶信息。Account由ATM類通過login登錄後使用:
public class ATM
{
Account acc;
//作為演示,省略了密碼驗證
public boolean login(String name)
{
if (acc != null) throw new IllegalArgumentException("Already logged in!");
acc = new Account(name);
return true;
}
public void deposit(float amt)
{
acc.deposit(amt);
}
public void withdraw(float amt) throws InsufficIEntBalanceException
{
acc.withdraw(amt);
}
public float getBalance()
{
return acc.getBalance();
}
public void logout ()
{
acc = null;
}
}
-