2016-05-29 99 views
1

我是Java新手。我剛剛閱讀了「核心Java」一書。我遇到了一個關於'條件&鎖'的問題。Java鎖狀態等待並通知:IllegalMonitorStateException

我從書中輸入了一段代碼到日食來做一些練習。

當我運行代碼時,「sufficientFund.wait();」行拋出IllegalMonitorStateException。爲什麼這裏有例外?

我在Google上搜索了一段時間,我知道「這個方法只應該被這個對象監視器的所有者所調用。」我認爲當前線程有鎖,因爲'bankLock.lock();'在wait()之前執行。 我認爲代碼的正確行爲是,當前線程應掛在sufficientFund.wait(),但它沒有。

package com.first.java; 

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

public class BankTranf { 

    private static final int NACCOUNT = 3; 
    public static final double INITAL_BALANCE = 1000; 

    public static void main(String[] args) { 

     Bank bank = new Bank(NACCOUNT, INITAL_BALANCE); 

     for (int i = 0; i < NACCOUNT; i++) { 

      TransferRunnable transferRunnable = new TransferRunnable(bank, i, INITAL_BALANCE); 

      Thread thread = new Thread(transferRunnable); 
      thread.start(); 
     } 

     System.out.println("press any key to exit."); 
     Scanner in = new Scanner(System.in); 
     in.nextLine(); 
     System.exit(0); 
    } 

} 

class Bank { 
    private final double[] account; 
    private Lock bankLock; 
    private Condition sufficientFund; 

    public Bank(int n, double initialBanlance) { 
     account = new double[n]; 
     for (int i = 0; i < account.length; i++) { 
      account[i] = initialBanlance; 
     } 

     bankLock = new ReentrantLock(); 
     sufficientFund = bankLock.newCondition(); 

    } 

    public void transfer(int from, int to, double amount) { 
     bankLock.lock(); 

     try { 
      while (account[from] < amount) { 
       System.out.println(Thread.currentThread().getName() + " does'nt hava enough money"); 
       sufficientFund.wait(); 
      } 

      System.out.println(Thread.currentThread()); 

      account[from] -= amount; 
      System.out.printf("%10.2f from %d to %d ", amount, from, to); 
      account[to] += amount; 
      System.out.printf(" Total balance: %10.2f%n", getTotalBalance()); 
      sufficientFund.signalAll(); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } finally { 
      bankLock.unlock(); 
     } 
    } 

    public double getTotalBalance() { 
     double d = 0; 
     bankLock.lock(); 
     try { 
      for (double n : account) { 
       d += n; 
      } 
      return d; 
     } finally { 
      bankLock.unlock(); 
     } 
    } 

    public int size() { 
     return account.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; 
     this.fromAccount = from; 
     this.maxAmount = max; 
    } 

    @Override 
    public void run() { 

     try { 
      while (true) { 
       int toAcount = (int) (bank.size() * Math.random()); 
       double amount = maxAmount * Math.random(); 
       bank.transfer(fromAccount, toAcount, amount); 
       Thread.sleep(4000/* (int)(DELAY*Math.random()) */); 
      } 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

我也試過另一種方式,我刪除了所有的鎖和條件,而不是使用「同步」,代碼運行正如我所料。

public synchronized void transfer(int from, int to, double amount) { 
     //bankLock.lock(); 

     try { 
      while (account[from] < amount) { 
       System.out.println(Thread.currentThread().getName() + " does'nt hava enough money"); 

       wait(); 
      } 

      System.out.println(Thread.currentThread()); 

      account[from] -= amount; 
      System.out.printf("%10.2f from %d to %d ", amount, from, to); 
      account[to] += amount; 
      System.out.printf(" Total balance: %10.2f%n", getTotalBalance()); 

      notifyAll(); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } finally { 

     } 
    } 

    public synchronized double getTotalBalance() { 
     double d = 0; 

     try { 
      for (double n : account) { 
       d += n; 
      } 
      return d; 
     } finally { 

     } 
    } 

回答

2

注意Condition作爲Java的任何類擴展Object,因此它具有wait方法從Object繼承,我相信您錯誤地調用這裏,那你的意思是打電話來等待條件的方法是Condition#await而不是wait

+0

是的,你是對的! – gfan