Search code examples
javamultithreadingproducer-consumerblockingqueue

Suspend consumer in producer/consumer pattern


I have producer and consumer connected with BlockingQueue.

Consumer wait records from queue and process it:

Record r = mQueue.take();
process(r);

I need pause this process for a while from other thread. How to implement it?

Now I think implement it such, but it's looks like bad solution:

private Object mLock = new Object();
private boolean mLocked = false;

public void lock() {
    mLocked = true;
}

public void unlock() {
    mLocked = false;
    mLock.notify();

}

public void run() {
    ....
            Record r = mQueue.take();
            if (mLocked) {
                mLock.wait();
            }
            process(r);
}

Solution

  • I think your solution is simple and elegant, and think you should keep it with some modifications. The modifications I propose are synchronization.

    Without it, thread interference and memory consistancy errors can (and very often does) occur. On top of that, you can't wait or notify on a lock you don't own (and you own it if you have it inside a synchronized block..). The fix is easy, just add a mLock synchronize block where you wait/notify on it. Also, as you're changing mLocked from a different thread you will want to mark it volatile.

    private Object mLock = new Object();
    private volatile boolean mLocked = false;
    
    public void lock() {
        mLocked = true;
    }
    
    public void unlock() {
        synchronized(mlock) {
            mLocked = false;
            mLock.notify();
        }
    
    }
    
    public void run() {
        ....
                Record r = mQueue.take();
                synchronized(mLock) {
                    while (mLocked) {
                        mLock.wait();
                    }
                }
                process(r);
    }