Waiting for an object to be initialized

java, wait

Solution

Firstly, yes `Object.wait()` and `Object.notify()` / `Object.notifyAll()` are what you need. Whether or not you use them directly is a different matter. Due to the ease of making mistakes programming directly with `wait/notify` it is generally recommended to use the concurrency tools added in Java 1.5 (see second approach below).

The traditional `wait/notify` approach:

Initialisation:

    synchronized (lockObject) {
        SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);
        lockObject.notifyAll();
    }

In the 'cancel' thread:

    synchronized (lockObject) {
        while (currentAnalysis == null) {
            try { lockObject.wait(); }
            catch Exception(e) { } // FIXME: ignores exception
        }
    }
    currentAnalysis.cancel();

Of course these could be synchronized methods instead of blocks. Your choice of `lockObject` will depend on how many 'cancel' threads you need etc. In theory it could be anything, i.e. `Object lockObject = new Object();` as long as you are careful the correct threads have access to it.

Note that it is important to put the call to `wait()` in a while loop here due to the possibility of spurious wakeups coming from the underlying OS.

A simpler approach would be to use a `CountDownLatch`, sparing you from the nuts and bolts of `wait()`&`notify()`:

(I'm making a couple of assumptions here in order to suggest a possibly cleaner approach).

    class AnalysisInitialiser extends Thread {

        private CountDownLatch cancelLatch = new CountDownLatch(1);
        private SpecialAnalysis analysis = null;

        @Override
        public void run() {
            analysis = new SpecialAnalysis(params);
            cancelLatch.countDown();
        }

        public SpecialAnalysis getAnalysis() {
            cancelLatch.await();
            return analysis;
        }
    }

Then in the thread that needs to send the cancel signal: (obviously you need to get hold of the `AnalysisInitialiser` object in some way)

    analysisInit.getAnalysis.cancel();

No concurrency primitive boilerplate, yay!

Problem

I have an object that is being initialized in a separate thread. Initialization can take several seconds while a local DB is being populated. ``` SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here); ``` I'm trying to implement a "cancel" button, that sets the object's `isCancelled` boolean to true. What is the proper Java way to implement this? ``` while (currentAnalysis == null) { } currentAnalysis.cancel(); ``` This method freezes the program as it appears to have entered a computationally inefficient loop. Is this a case where I could use `Object.wait()`? My current bad/semi-successful solution is: ``` while (currentAnalysis == null) { Thread.sleep(500); } currentAnalysis.cancel(); ``` Thanks!

Original source

Related problems