我创建了一个使用SQLite4Java连接到SQLite数据库的Java程序。
我从串口读取并将值写入数据库。这在开始时运行良好,但现在我的程序已经增长,我有几个线程。我试图用一个SQLiteQueue变量来处理它,该变量用这样的方式执行数据库操作:
public void insertTempValue(final SQLiteStatement stmt, final long logTime, final double tempValue)
{
if(checkQueue("insertTempValue(SQLiteStatement, long, double)", "Queue is not running!", false))
{
queue.execute(new SQLiteJob<Object>()
{
protected Object job(SQLiteConnection connection) throws SQLiteException
{
stmt.bind(1, logTime);
stmt.bind(2, tempValue);
stmt.step();
stmt.reset(true);
return null;
}
});
}
} // end insertTempValue(SQLiteStatement, long, double)
但是现在我的SQLite级别无法执行语句报告:
DB[1][U]: disposing [INSERT INTO Temperatures VALUES (?,?)]DB[1][U] from alien thread
SQLiteDB$6@8afbefd: job exception com.almworks.sqlite4java.SQLiteException: [-92] statement is disposed
因此执行不会发生。
我试图弄清楚错误是什么,我认为我需要一个Java包装器,它可以从其他线程经过的单个线程调用所有数据库操作。
这是我的问题,我不知道如何以一种好的方式实现这一点。 如何进行方法调用并确保它始终从同一个线程运行?
答案 0 :(得分:1)
将所有数据库访问代码放入包中,并将所有类包都设为私有。使用运行循环的run()方法编写一个Runnable或Thread子类。循环检查排队的信息请求,并运行相应的数据库访问代码以查找信息,将信息放入请求并在返回队列之前标记请求完成。
客户端代码将数据请求排队并等待答案,可能是阻塞,直到请求标记为完成。
数据请求看起来像这样:
public class InsertTempValueRequest {
// This method is called from client threads before queueing
// Client thread queues this object after construction
public InsertTempValueRequest(
final long logTime,
final double tempValue
) {
this.logTime = logTime
this.tempValue = tempValue
}
// This method is called from client threads after queueing to check for completion
public isComplete() {
return isComplete;
}
// This method is called from the database thread after dequeuing this object
execute(
SQLiteConnection connection,
SQLiteStatement statement
) {
// execute the statement using logTime and tempValue member data, and commit
isComplete = true;
}
private volatile long logTime;
private volatile double tempValue;
private volatile boolean isComplete = false;
}
这样可行,但我怀疑实施过程会有很多麻烦。我认为你也可以使用一个只允许一个线程访问数据库的锁,并且 - 这与你现有的情况不同 - 通过从头开始创建数据库资源 - 包括语句 - 开始访问,并在释放锁之前处置这些资源。
答案 1 :(得分:0)
我找到了解决问题的方法。我现在已经实现了一个包装类,它使用ExecutorService对我的旧SQLite类进行所有操作,灵感来自Thread Executor Example并从Java Doc ExecutorService获得了正确的用法。