Search code examples
javajava.util.concurrent

Java concurrency - is there a reverse CountDownLatch?


There are some user-activated long running tasks that execute in the background. Since the system is multi-user, it is not practical to know how many might be running at any given time.

Normally, these tasks can execute in the background and simply complete when they are finished. There are certain limited user actions that require all such tasks complete prior to proceeding. A blocking synchronization mechanism was required. I implemented the logic to do this, but realized that the behavior I needed was effectively the opposite of the CountDownLatch:

  • when an allowed task (in my case, a background task) executes, it would increment the count non-bounded (or bounded)

  • when finished it would decrement the count

  • there would be blocking method(s) that only block when the count > 0

I found no such class available in java.util.concurrent. Does anyone know if such a thing exists anywhere?


Solution

  • In case anyone ever wants to know what I ended up doing, recording that here:

    I ended up needing two locks:

        this.workInProgressLock = new ReentrantReadWriteLock(true);
        this.singleFileLock = new Semaphore(1, true);
    

    The ReadWriteLock works mostly as described in the comment above. The main issue is that writeLock requests are given preference as they pend. Thus sequencing is not as easily controllable as it should be.

    The Semaphore does count UP, but works opposite as I needed. Why did I add one? I quickly realized that Background Processing (Tasks) are a two-way street! As initially described, Background Processes were allowed to start whenever needed. When running during certain 'critical sections' of the Application, major problems arose. Consequently, the App-side needed a way to 'lock-out' the Background Tasks. The single count Semaphore was a perfect fit for that purpose.

    It would be nice to have a "BackgroundProcessingLock" somewhere (Guava, where-ever):

    public interface BackgroundProcessingLock {
    
        void allowBackgroundTasks();
    
        void preventBackgroundsTasks(boolean wait);  
    
        void wait();  // simply waits until all background tasks complete
    
        void startBackgroundTask();
    
        void completeBackgroundTask();
    
        void setMaxNumberOfBackgroundTasks(int maxParallelBackgroundTasks);
    
    }