2015-09-06 12 views
1

解決我的問題的Java:幫助設計出引起SQLLite僵局

我找到了解決我的問題是,以取代與包裝「Sqlite4Java」 sqilte的JDBC驅動程序,即解決了這一問題的唯一途徑並且稍後還允許數據庫處理跨多個線程的多個連接,從而減少了限制。

編輯:

這個問題是關於只用Java代碼解決問題。該問題是由SQLLite間接引起的,但無法通過更改數據庫系統或SQL代碼來解決。我提到SQLLite是因爲否則用戶會指向實際上破壞項目強制需求的無用解決方案(定義的用戶界面和行爲以及SQLite作爲DBMS,因爲它可以在沒有服務器的情況下運行,並且項目會自動更正)。

EDIT2: 死鎖發生在Java端,這是不容易看到它,我調試了一整天意識到之前,忘記SQLLite,我需要找到一種方式來獲得停車場工作像一個監視器,但沒有與​​發生衝突導致死鎖


目前,我有以下情況:

我有一個簡單的停車類,實際上它是一個顯示器,其中CL客戶從其他線程調用lendVehicle方法。

public class Parking{ 

    private final long  parkId; 
    private final ParkingAPI sqlLayer; 
    private final Lock  lock = new ReentrantLock(); 
    private final Condition notEmpty = lock.newCondition(); 

    public Parking(long mparkId, ParkingAPI api){ 
     sqlLayer = api; 
     parkId = mparkId; 
    } 

    long lendVehicle(){ 
     lock.lock(); 
     try{ 
      while(sqlLayer.countVehicles(parkId) == 0) 
       notEmpty.await(); 

      return sqlLayer.lend(parkId); 

     } finally{ 
      lock.unlock(); 
     } 
    } 

    void giveBackVehicle(long vehicleId){ 
     lock.lock(); 
     try{ 
      sqlLayer.giveBack(vehicleId,parkId); 
      notEmpty.signal(); 

     } finally{ 
      lock.unlock(); 
     } 
    } 

當我嘲笑只有一個原子計數器的SQL層,類然而完美的作品,因爲應用程序是使用SQL精簡版我要保護併發訪問的連接(基本上我可以在任何執行1個查詢給定的時間,因爲SQL Lite)。

目前的代碼是​​而不是DBLayer對象(在所有類中共享)。

class ParkingQuery implements ParkingAPI{ 

    private final DBLayer connection; 

    public SQLLayer(DBLayer db){ 
     connection = db; 
    } 

    @Override 
    int lend(long parkId){ 
     synchronized(connection){ 
      return connection.lendVehicleFromPark(parkId); 
     } 
    } 

    @Override 
    int countVehicles(long parkId){ 
     synchronized(connection){ 
      return connection.countVehiclesQuery(parkId); 
     } 
    } 

    @Override 
    void giveBack(long vehicleId, long parkId){ 
     synchronized(connection){ 
      connection.giveBackVehicle(parkId, vehicleId); 
     } 
    } 
} 

問題是同步的部分,它不能很好地與Parking的監視器一起玩:這實際上導致了死鎖。

如何保存停車功能? (不能刪除ParkingQuery上的synchronized,因爲如果查詢不同步,並且壞事情開始發生,SQLite就會爆炸)。

請注意,併發訪問SQLLite是強制性的,因爲這是一個學校項目。

編輯: 期望中的停車行爲: 如果用戶希望把機動車輛,這是不可用的用戶必須等待別人放貸返回的車輛。

+0

如果Parking是唯一使用ParkingAPI更新數據庫的類,我會說你不需要同時使用這兩個類。 SQLite查詢位於同步塊內,因此它是線程安全的。我不明白爲什麼同步關鍵字不足以停放。我不喜歡你的命名。 ParkingAPI?我期望ParkingDAO或ParkingRepository。 – duffymo

+0

除了來自域範圍的命名外,如果2個用戶需要從相同的停車位出借並且只有1個車輛可用,則想要的行爲是一個用戶將等待車輛變得可用,而沒有條件變量兩者都將看到車輛計數= = 1並繼續貸款查詢,這可能很難預測副作用。 – GameDeveloper

+0

當然,它不是唯一一個有註冊,登錄,增加新停車和車輛等功能的班級,除了藉助條件變量外,所有工作都是如此。 – GameDeveloper

回答

2

此代碼:

long lendVehicle(){ 
     lock.lock(); 
     try{ 
      ... 
    } 

是錯誤的。您基本上鎖定,因此它不保證解鎖,因爲它位於try塊之外。嘗試更恰當地分解問題。你有一個生產者,這是汽車的回報,然後你的消費者就是在借汽車。所以你知道你的「汽車」只能容納N輛汽車(比如說可以說10個汽車)。所以如果你的緩衝器(汽車很多)已滿,你不想讓更多的汽車得到回報(想想試圖在沒有剩餘點的車庫裏停車)。

現在你可以簡單地檢查你的回車功能,如果緩衝區已滿並且它忽略了操作。租借汽車時,要確保該地段不是空的。

+0

也許問題是停車有無限的車限制? – GameDeveloper

+0

這不是一個有效的理由。解決小N然後推廣 – Woot4Moo