Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting for an object to be initialized

Tags:

java

wait

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!

like image 530
Megatron Avatar asked May 30 '14 15:05

Megatron


People also ask

What does it mean to initialize objects?

initializing means setting value to an object.(does not necessarily create new instance). assigning is self descriptive. assign a value to an object.

What is required to initialize an object?

Objects can be initialized using new Object() , Object. create() , or using the literal notation (initializer notation). An object initializer is a comma-delimited list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ( {} ).

Is it necessary to initialize object in Java?

Classes and objects in Java must be initialized before they are used.


1 Answers

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!

like image 174
willjcroz Avatar answered Oct 08 '22 03:10

willjcroz