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!
initializing means setting value to an object.(does not necessarily create new instance). assigning is self descriptive. assign a value to 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 ( {} ).
Classes and objects in Java must be initialized before they are used.
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()
¬ify()
:
(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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With