- 鎖用來保護代碼片段,任何時刻只能有一個線程執行被保護的代碼。
- 鎖可以管理試圖進入被保護代碼段的線程。
- 鎖可以擁有一個或是多個相關的條件對象。
- 每個條件對象管理那些已經進入被保護的代碼段但還不能運行的線程。
synchronized內部鎖和條件wait存在一些侷限
- 不能中斷一個正在試圖獲得鎖的線程
- 試圖獲得鎖時不能設定超時。
- 每個鎖僅有單一的條件,可能是不夠的。
void notify():隨機選擇一個在該對象上調用wait方法的線程,解除其阻塞狀態。該方法只能在該方法只能在同步方法或是同步塊內部調用。如果當前線程不是對象鎖的持有者,該方法拋出一個IllegalMonitorStateException異常。
void wait():導致線程進入等待狀態直到它被通知。該方法只能在同步方法中調用。如果當前線程不是對象鎖的持有者,該方法拋出一個IllegalMonitorStateException異常。
void wait(long millis) void wait(long millis , int nanos)
參數:millis 毫秒數
nanos 納秒數 <1 000 000
導致線程進入等待狀態直到他被通知或者經過指定的時間。這些方法只能在一個同步方法中調用。如果當前線程不是對象鎖的持有者,該方法拋出一個IllegalMonitorStateException異常。
package com.bing.jia;
public class UnsynchBankTest{
public static final int NACCOUNTS = 100;//這家銀行有多少個賬號
public static final double INITIAL_BALANCE = 1000;//每個賬號開始的金額
public static void main(String[] args) {
Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
int i;
for(i=0;i<NACCOUNTS;i++){
TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);
Thread t = new Thread(r);
t.start();
}
}
}
class Bank extends Thread{
private final double[] accounts;//數組的長度爲銀行賬號數,數組的值爲銀行賬號的金額
public Bank(int n,double initialBalance){
accounts = new double[n];
for(int i=0;i<accounts.length;i++){
accounts[i] = initialBalance;
}
}
public synchronized void transfer(int from,int to,double amount) throws InterruptedException{
if(accounts[from]<amount){
wait();
//return;
}
System.out.println("Thread.currentThread():"+Thread.currentThread());
accounts[from] -= amount;
System.out.println("轉賬金額數amount:"+amount+" from:"+from+" to:"+to);
accounts[to] += amount;
System.out.println("getTotalBalance()賬戶剩餘金額:"+getTotalBalance());
notifyAll();
}
public double getTotalBalance(){
double sum = 0;
for(double a : accounts){
sum += a;
}
return sum;
}
public int size(){
return accounts.length;
}
}
class TransferRunnable implements Runnable{
private Bank bank;
private int fromAccount;
private double maxAmount;
private int DELAY = 10;
public TransferRunnable(Bank b,int from,double max){
bank = b;
fromAccount = from;
maxAmount = max;
}
@Override
public void run() {
try {
while(true){
int toAccount = (int) (bank.size()*Math.random());//隨機選一個要收賬的賬號Math.random()返回0-1的小數
double amount = maxAmount*Math.random();//轉賬的金額數,始終不能比賬號總額大
bank.transfer(fromAccount, toAccount, amount);
Thread.sleep((int)(DELAY*Math.random()));
Thread.sleep(DELAY);
}
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}