2015-09-06 64 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