Managing threads accessing a database with Java Managing threads accessing a database with Java sqlite sqlite

Managing threads accessing a database with Java


(I will assume you are using JDBC for your database queries and that you have control over the code running the queries)

I would centralize all database accesses in a singleton class which would keep the last PreparedStatement running the current query in a single thread ExecutorService. You could then ask that singleton instance things like isQueryRunning(), runQuery(), cancelQuery() that would be synchronized so you can decide to show a message to the user whenever the computation should be canceled, cancel it and start a new one.

Something like (add null checks and catch (SQLException e) blocks):

public class DB {    private Connection cnx;    private PreparedStatement lastQuery = null;    private ExecutorService exec = Executors.newSingleThreadExecutor(); // So you execute only one query at a time    public synchronized boolean isQueryRunning() {        return lastQuery != null;    }    public synchronized Future<ResultSet> runQuery(String query) {        // You might want to throw an Exception here if lastQuery is not null (i.e. a query is running)        lastQuery = cnx.preparedStatement(query);        return exec.submit(new Callable<ResultSet>() {            public ResultSet call() {                try {                    return lastQuery.executeQuery();                } finally { // Close the statement after the query has finished and return it to null, synchronizing                    synchronized (DB.this) {                        lastQuery.close();                        lastQuery = null;                    }                }            }            // Or wrap the above Future<ResultSet> so that Future.cancel() will actually cancel the query    }    public synchronized void cancelQuery() {        lastQuery.cancel(); // I hope SQLite supports this        lastQuery.close();        lastQuery = null;    }}


A solution to your problem could be Thead.stop(), which has been deprecated centuries ago (you can find more on the topic here).

To implement the similar behavior it is suggested to use the Thread.interrupt(), which is (in the context of Task) the same as the the Task.cancel().

Solutions:

  • Fill your calculationMethod with isCancelled() checks.
  • Try to interrupt an underling operation through an other Thread.

The second solution is probably what you are looking for, but it depends on the actual code of the calculationMethod (which I guess you can't share).

Generic examples for killing long database operations (all of this are performed from another thread):

  • Kill the connection to the Database (assuming that the Database is smart enough to kill the operation on disconnect and then unlock the database).
  • Ask for the Database to kill an operation (eg. kill <SPID>).

EDIT:

I hadn't see that that you specified the database to SQLite when I wrote my answer. So to specify the solutions for SQLite:

  • Killing the connection will not help
  • Look for the equivalent of sqlite3_interrupt in your java SQLite interface


Maybe you can invoke thread instance t1, t1.interrupt() method, then in the run method of thread( Maybe calculationMethod), add a conditional statement.

 public void run() {        while (!Thread.currentThread().isInterrupted()) {            try {                // my code goes here            } catch (IOException ex) {                log.error(ex,ex)            }        }    }