Quantcast
Channel: Pausing and resuming a concurrent database update queue - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 3

Pausing and resuming a concurrent database update queue

$
0
0

I have a class DatabaseQueue which asynchronously runs SQLite updates that it takes from a LinkedBlockingQueue.

I implemented a pausing mechanism for this class which should ideally stop the execution of the queue as soon as possible and then wait for it to be unpaused before executing more queries.

I'm very new to concurrent programming but I managed to get this working using multiple ReentrantLock's and Condition's. This seems very verbose and clumsy though, especially with all the lock()'s and unlock()'s.

In addition to this, I also don't like how I have to execute an additional dummy query just to get the executor thread to continue its loop. What would be a better way to implement this?

import java.sql.Connection;import java.sql.SQLException;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;public class DatabaseQueue {    private static final LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();    private static final QueueExecutor executor = new QueueExecutor();    private static boolean locked = false;    private static ReentrantLock lockAttempted = new ReentrantLock();    private static ReentrantLock lockAcquired = new ReentrantLock();    private static Condition attempted = lockAttempted.newCondition();    private static Condition acquired = lockAcquired.newCondition();    public static void start() {        if (locked) {            locked = false;            lockAttempted.lock();            attempted.signal(); //Signal to resume queue execution            lockAttempted.unlock();        } else {            executor.start();        }    }    public static void pause() {        locked = true;        if (queue.isEmpty()) {            queue.add("SELECT 1");        }        lockAcquired.lock();        acquired.awaitUninterruptibly(); //Wait for the lock to be acquired        lockAcquired.unlock();    }    public static void queue(String update) {        queue.add(update);    }    public static class QueueExecutor extends Thread {        public QueueExecutor() {            setName("Database Queue Executor");            setDaemon(true);        }        @Override        public void run() {            Connection connection = Database.getConnection();            while (true) {                try {                    if (locked) {                        lockAcquired.lock();                        acquired.signal(); //Signal that the lock has been acquired                        lockAcquired.unlock();                        lockAttempted.lock();                        attempted.awaitUninterruptibly(); //Wait for the lock to be released                        lockAttempted.unlock();                    }                    String update = queue.take();                    connection.createStatement().executeUpdate(update);                    Database.update(update);                } catch (InterruptedException | SQLException e) {                    e.printStackTrace();                }            }        }    }}

Viewing all articles
Browse latest Browse all 3

Latest Images

Trending Articles



Latest Images