如何实现Java单数据库线程

时间:2014-04-21 19:32:23

标签: java multithreading sqlite database-connection single-threaded

我创建了一个使用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包装器,它可以从其他线程经过的单个线程调用所有数据库操作。

这是我的问题,我不知道如何以一种好的方式实现这一点。 如何进行方法调用并确保它始终从同一个线程运行?

2 个答案:

答案 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获得了正确的用法。