简体   繁体   中英

synchronization with executorService

i wrote tthe below method to insert records using threads, but at run time i receive "[SQLITE_BUSY] The database file is locked (database is locked)" error,and i think could be due to conflict of sqlite statement.

i just want to know i am wusing the executorservice correctly in the "insertRecord" method? is there any other variables shoule have been synchronizedß

code :

public void insertRecord(String nodeID, String lat, String lng, String xmlpath) throws SQLException, ClassNotFoundException {

    if (this.isTableExists(this.TABLE_NAME)) {

        InsertRun insRun = new InsertRun(this.psInsert, nodeID, lat, lng, xmlpath);
        this.executor.execute(insRun);

    } else {
        Log.e(TAG, "insertRecord", "table: ["+this.TABLE_NAME+"] does not exist");
    }
}

public void flush() throws SQLException {
    this.psInsert.executeBatch();

    this.psInsert.close();
    this.connInsert.close();

    Log.d(TAG, "insertRecord", "the rest of the records flushed into data base table.");
}

private class InsertRun implements Runnable {

    private PreparedStatement psInsert = null;
    private String nodeID;
    private String lat;
    private String lng;
    private String xmlPath;

    public InsertRun(PreparedStatement psInsert, String nodeID, String lat, String lng, String xmlpath) {
        // TODO Auto-generated constructor stub
        this.psInsert = psInsert;
        this.nodeID = nodeID;
        this.lat = lat;
        this.lng = lng;
        this.xmlPath = xmlpath;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            this.psInsert.setString(1, this.nodeID);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            this.psInsert.setString(2, this.lat);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            this.psInsert.setString(3, this.lng);
        } catch (SQLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try {
            this.psInsert.setString(4, this.xmlPath);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            this.psInsert.addBatch();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        synchronized(this) {
            if (++batchCnt == SysConsts.BATCH_SIZE) {
                try {
                    this.psInsert.executeBatch();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                batchCnt = 0;

                Log.d(TAG, "InsertRun", SysConsts.BATCH_SIZE+" records inserted.");
            }
        }

    }

}

SQLite is not a database suitable for concurrent access. You cannot modify your database concurrently:

Multiple processes can have the same database open at the same time. Multiple processes can be doing a SELECT at the same time. But only one process can be making changes to the database at any moment in time, however.

.

When SQLite tries to access a file that is locked by another process, the default behavior is to return SQLITE_BUSY

Read this for details (and simply give up multithreading in your app...)

Additionally, good concurrency design considerations can be difficult to offer without know alot more about the program. Suggest perusing through Java Concurrency in Practice if you plan on writing more multi-threaded applications.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM