Singleton with a Listener versus Join - java

I inherited this code from a previous developer (lol). I'm considering changing this to support a join instead of using a listener kind of callback.
My requirements:
1. I need to have the calling thread wait until the DoMath class thread has completed.
2. I need to prevent other threads from calling it.
This, in another thread (and class) - :
DoMath.getInstance().performMathCalc();
It doesn't wait or sleep of course when it calls this:
public class DoMath {
protected math calc() {
}
public static DoMath getInstance() {
if(_instance == null) {
_instance = new DoMath();
}
return _instance;
}
// perform a synchronous math calc, and return a boolean indicating success or failure.
public boolean performMathCalc() {
MathEngine.setApplicationMode(MathEngine.AUTO);
MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
return true;
}
// perform an async math calc, and call back the listener when done
public void performMathCalc(final listener client) {
Thread mathThread = new Thread(new Runnable() {
public void run() {
boolean result = performMathCalc();
client.mathFinished(result);
}
});
mathThread.setDaemon(true);
mathThread.start();
}
public static interface listener {
public void mathFinished(boolean success);
}
protected static DoMath _instance;
}
So, is it better to just use the listener or implement a join in the calling class?

Do note that this:
public static DoMath getInstance() {
if(_instance == null) {
_instance = new DoMath();
}
return _instance;
}
is not thread-safe. To ensure that your class really is a Singleton (relative to its ClassLoader) you must either synchronize that method or initialize the _instance member in its declaration. Either way, _instance must be private or final or both.
As for your actual requirements,
(1) it seems you want to either change an asynchronous call into a synchronous one, or to put a synchronous wrapper around it. You can do the latter via the existing listener interface, which would preserve the ability to perform asynchronous jobs. If you don't want that then instead of joining, skip launching a new thread at all: just run the computation in the current thread.
(2) How you might prevent multiple threads from running calculations at the same time depends in part on how you address issue (1). If you make everything synchronous then you can just make DoMath.performMathCalc() a synchronized method. If you retain the asynchronous computation option then you could look to package java.util.concurrent.locks for classes that can help you.

Do you really want to pause your thread until the other one as finished? You should never, ever block the main thread.
The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,
t.join();
causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.
(from java docs)
Also, does performMatchCalc() needs to be public ?
Now, at first glance that code actually looks correct, but, you can still prevent someone from starting another calculation. Perhaps with something similar of this :
public class DoMath {
private Thread mathThread;
protected math calc() {
}
public static DoMath getInstance() {
if(_instance == null) {
_instance = new DoMath();
}
return _instance;
}
// perform a synchronous math calc, and return a boolean indicating success or failure.
public boolean performMathCalc() {
if(null != mathThread && mathThread.isAlive())
return false;
MathEngine.setApplicationMode(MathEngine.AUTO);
MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
return true;
}
// perform an async math calc, and call back the listener when done
public void performMathCalc(final listener client) {
//re-start calculation? if so
if(null != mathThread && mathThread.isAlive()) {
matchThread.interrupt();
matchThread = null;
}
mathThread = new Thread(new Runnable() {
public void run() {
boolean result = performMathCalc();
client.mathFinished(result);
}
});
mathThread.setDaemon(true);
mathThread.start();
}
public static interface listener {
public void mathFinished(boolean success);
}
protected static DoMath _instance;
}

I need to have the calling thread wait until the DoMath class thread has completed.
You already have this. Note how there are two performMathCalc methods:
The first method takes no arguments and performs the calculation on the caller thread, then returns the result. This fulfills your first requirement.
The second method is an asynchronous wrapper for the first; it allows the caller to kick off a calculation, then go off an do something else with the understanding that, at some point in the future, someone will be notified that the operation has completed. This is useful functionality, so I would keep it.
I do see one issue with the asynchronous wrapper, however: the listener will not be notified in the event that the core performMathCalc() method throws an exception. Consider using a try/catch/finally block to ensure the listener always gets notified, even if an error occurs. You'll need to decide whether to add a second callback to your listener (e.g., mathFailed) or to simply call mathFinished(false) on errors.
I need to prevent other threads from calling it.
We can accomplish this easily enough, and since the asynchronous version simply delegates to the synchronous version, we only need to lock down the synchronous version. The simplest way would be to mark the method as synchronized, since your class only provides one logical function:
public synchronized boolean performMathCalc() {
MathEngine.setApplicationMode(MathEngine.AUTO);
MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
return true;
}
Alternatively, if you end up extending your DoMath class to perform other kinds of operations that are not mutually exclusive, you can synchronize on operation-specific locks.
That leaves us with your singleton accessor:
public static DoMath getInstance() {
if (_instance == null) {
_instance = new DoMath();
}
return _instance;
}
This conditional initialization is not thread-safe. Your singleton is very simple and doesn't have any up-front initialization costs, so simply mark _instance as final static and initialize it in the declaration.

Related

How to design a task queue with mutually exclusive but independently concurrent methods?

I was asked a concurrency question in a job interview, that eventually boiled down to the following requirements. I was able to achieve #2 through #4 simply by using mutual exclusion, but not #1.
Design a task queue with the following methods:
public void registerCallback(Runnable task)
public void eventFired()
Multiple threads should be able to put tasks on the queue, possibly concurrently.
eventFired should only be invoked once.
If eventFired has been previously invoked, any later invocation of either methods should throw an exception.
If eventFired is invoked while registerCallback is executing, delay firing the event until a later time.
If registerCallback is invoked while eventFired is executing, throw an exception.
ReentrantReadWriteLock seems promising, because registerCallback can acquire the read lock, and eventFired the write lock, but that doesn't solve a race condition where registerCallback is invoked, and then eventFired.
Any ideas?
ReentrantReadWriteLock seems promising, because registerCallback can acquire the read lock, and eventFired the write lock, but that doesn't solve a race condition where registerCallback is invoked, and then eventFired.
Registering a callback, in other words, modifying a data structure, while holding a read lock, is never a good idea. You’d need another thread safe construct for the storage of the callbacks and complicate the code unnecessarily.
The operation of registering a callback, like storing a reference into some collection or instantiating whatever kind of node object, is trivial enough to allow using an ordinary mutual exclusive lock, as it is not held for long.
Whether you use synchronized, a Lock, or a state supporting atomic updates, in either case, the race condition does not exist, as there can’t be an overlap of registerCallback or eventFired. All of these approaches bring an order into these operations, when used correctly. So every registerCallback is either, before the first eventFired or after it.
Implementing this can be straight-forward:
public class JobQueue {
private List<Runnable> callbacks = new ArrayList<>();
public synchronized void registerCallback(Runnable task) {
if(callbacks == null) {
throw new IllegalStateException("Event already fired");
}
callbacks.add(Objects.requireNonNull(task));
}
public void eventFired() {
List<Runnable> list;
synchronized(this) {
list = callbacks;
callbacks = null;
}
if(list == null) {
throw new IllegalStateException("Can only fire once");
}
for(Runnable r: list) r.run();
}
}
The code executed within the synchronized blocks is so short, that contention will be irrelevant for most practical use cases. Implementing the same with a Lock would be straight-forward, but there won’t be any advantage. In fact, JVM specific optimizations may render the synchronized based solution more efficient.
For completeness, here an atomic update based solution:
public class JobQueue {
private static final Runnable DONE = () -> {};
private final AtomicReference<Runnable> pending = new AtomicReference<>();
public void registerCallback(Runnable task) {
Objects.requireNonNull(task);
for(;;) {
Runnable previous = pending.get();
if(previous == DONE) throw new IllegalStateException("Event already fired");
if(pending.compareAndSet(previous, sequence(previous, task))) return;
}
}
public void eventFired() {
Runnable previous = pending.getAndSet(DONE);
if(previous == DONE) throw new IllegalStateException("Can only fire once");
if(previous != null) previous.run();
}
static Runnable sequence(Runnable a, Runnable b) {
return a == null? b: () -> { a.run(); b.run(); };
}
}
Actually, the executions of multiple registerCallback and/or eventFired invocations may overlap, but in that case, only one can perform the critical atomic update successfully. This brings an order into the operations, making at most one eventFired invocation successful and categorizing all registerCallback invocations as made before or after that.

How can I synchronize the class so that I can use from UI thread and background threads?

I have a utility class as follows:
public class MetaUtility {
private static final SparseArray<MetaInfo> metaInfo = new SparseArray<>();
public static void flush() {
metaInfo.clear();
}
public static void addMeta(int key, MetaInfo info) {
if(info == null) {
throw new NullPointerException();
}
metaInfo.append(key, info);
}
public static MetaInfo getMeta(int key) {
return metaInfo.get(key);
}
}
This class is very simple and I wanted to have a "central" container to be used across classes/activities.
The issue is threading.
Right now it is populated (i.e the addMeta is called) only in 1 place in the code (not in the UI thread) and that is not going to change.
The getter is accessed by UI thread and in some cases by background threads.
Carefully reviewing the code I don't think that I would end up with the case that the background thread would add elements to the sparse array while some other thread would try to access it.
But this is very tricky for someone to know unless he knew the code very well.
My question is, how could I design my class so that I can safely use it from all threads including UI thread?
I can't just add a synchronized or make it block because that would block the UI thread. What can I do?
You should just synchronize on your object, because what your class is right now is just a wrapper class around a SparseArray. If there are thread level blocking issues, they would be from misuse of this object (well, I guess class considering it only exposes public static methods) in some other part of your project.
First shoot can be with synchronized.
#Jim What about the thread scheduling latency?
Android scheduler is based on Linux and it is known as a completely fair scheduler (CFS). It is "fair" in the sense that it tries to balance the execution of tasks not only based on the priority of the thread but also by tracking the amount of execution time that has been given to a thread.
If you'll see "Skipped xx frames! The application may be doing too much work on its main thread", then need some optimisations.
If you have uncontended lock you should not be afraid of using synchronized. In this case lock should be thin, which means that it would not pass blocked thread to OS scheduler, but would try to acquire lock again a few instructions after. But if you still would want to write non-blocking implementation, then you could use AtomicReference for holding the SparseArray<MetaInfo> array and update it with CAS.
The code might be smth like this:
static AtomicReference<SparseArray<MetaInfo>> atomicReference = new AtomicReference<>();
public static void flush() {
atomicReference.set(new SparseArray<MetaInfo>);
}
public static void addMeta(int key, MetaInfo info) {
if(info == null) {
throw new NullPointerException();
}
do {
SparseArray<MetaInfo> current = atomicReference.get();
SparseArray<MetaInfo> newArray = new SparseArray<MetaInfo>(current);
// plus add a new info
} while (!atomicReference.compareAndSet(current, newArray));
}
public static MetaInfo getMeta(int key) {
return atomicReference.get().get(key);
}

Multiple threads calling a method while blocking if another method is called from another thread

Suppose there are two methods methodA() and methodB() that are called from distinct threads. What I want is when methodA() is called then the thread that called methodB() be blocked until methodA() is finished, and the other way round. This can be easily achieved with a semaphore:
private Semaphore semaphore = new Semaphore(1, true);
public void methodA() {//ignored try catch finally
semaphore.acquire();
//do stuff
semaphore.release();
}
public void methodB() {
semaphore.acquire();
//do stuff
semaphore.release();
}
But the thing is that I want multiple threads executing concurrently methodA() or methodB(). Multiple threads should be able to execute at the same time methodA() so long no one executes methodB(); the above solution does not work in this case because if a thread executes methodA() no other thread can execute methodA() even if there is no thread executing methodB().
Any other solution I can think of either needs synchronization in methods or does something else that does not allow multiple threads executing a single method if no threads execute the other one.
This is a situation very much like a trafficlight at a crossroads. Either road A gets to pass or road B, but never both simultaneously.
So let's say we have a TrafficLight class that acts a little like a Semaphore that monitors two roads "A" and "B". A thread wanting to pass "A" can ask permission for "A" and shall be granted that permission, or block if a "B" permission has not been released, and vice versa.
In the past I have made such a TrafficLight class as an exercise (which can actually monitor more than 2 states) :
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class TrafficLight<T> {
private ReentrantLock lock = new ReentrantLock(true);
private Condition switched = lock.newCondition();
private int registered;
private int maxBeforeYield = 20;
private T state;
public void acquire(T t) throws InterruptedException {
lock.lock();
try {
while ((state != null && !state.equals(t)) || maxBeforeYield == 0) {
switched.await();
}
if (state == null) {
state = t;
}
registered++;
maxBeforeYield--;
} finally {
lock.unlock();
}
}
public void release() {
lock.lock();
try {
registered--;
if (registered == 0) {
state = null;
maxBeforeYield = 20;
switched.signalAll();
}
} finally {
lock.unlock();
}
}
}
Note the maxBeforeYield : one problem the TrafficLight may encounter is that so a flood of requests for "A" is so great, that requests for "B" never get a chance. Therefore the TrafficLight counts requests, and after a number of requests (maxBeforeYield) it starts blocking "A" requests as well, then nicely waits until all permissions have been returned, and then gives another state a chance, the ReentrantLock needs to be fair, to make sure the 'direction' switches unless only requests for the same direction are blocked.
Given this TrafficLight class you could change your code into :
private TrafficLight<String> trafficLight = new TrafficLight<>();
public void methodA() {//ignored try catch finally
trafficLight.acquire("A");
//do stuff
trafficLight.release();
}
public void methodB() {
trafficLight.acquire("B");
//do stuff
trafficLight.release();
}
Sounds like you want a reader/writer lock (e.g., java.util.concurrent.locks.ReentrantReadWriteLock). It allows any number of 'readers' to use the resource at the same --OR-- it allows exactly one 'writer' to use it, but not both.
A good implementation, like the Java version, will be slightly complicated by the need to provide 'fairness.' E.g., it must not 'starve' a writer that wants the resource even when there are so many readers that there is never a moment when the resource is idle.

When to use synchronized in Java

I hope this is going to be enough information, so here it goes. If you need more info, lemme know in the comments.
I have a class that has two inner classes. The inner classes each have two methods that call a method in the outer class. So, it looks like this:
public OuterClass {
private boolean outerMethodHasBeenCalled = false;
private void outerMethod() {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
private FirstInnerClass {
public void someMethod() {
outerMethod();
}
}
private SecondInnerClass {
public void someOtherMethod() {
outerMethod();
}
}
}
It's important to note that:
This is for an Android app. Instances of FirstInnerClass and SecondInnerClass are passed to a WebView as a JavaScript interface, so someMethod and someOtherMethod can be called at any time, in no particular order.
I currently have a problem with the existing code (without the synchronized keyword) where outerMethod is called pretty much at the exact same time (I print out a log message, and they're timestamped to the 1000th of a second) by different objects. My app then 'does stuff' twice because outerMethodHasBeenCalled is still false when outerMethod was called. This is not okay, and it is exactly what I'm trying to prevent. My app should only 'do stuff' once and only once: the first time outerMethod is called.
It might sound like I have multiple instances of OuterClass, but rest assured that it's only one instance of OuterClass.
It's important that my app 'does stuff' only the first time outerMethod gets called (I hope that's evident by now). All subsequent calls are essentially ignored. Whichever inner class calls outerMethod first -- doesn't matter.
So, is it appropriate to use the synchronized keyword in this case?
Yup, given what you've laid out above, I'd go with:
private synchronized void outerMethod() {
...
}
Note, this will have the side-effect of blocking one of the callers until the outerMethod() completes. If that is acceptable, cool. If the intent is merely that the code in outerMethod() is run once, and it is OK for the second caller not to be delayed if the first caller is running outerMethod(), you might consider:
public OuterClass {
private AtomicBoolean outerMethodHasBeenCalled = new AtomicBoolean();
private void outerMethod() {
if (outerMethodHasBeenCalled.compareAndSet(false, true)) {
// do stuff
}
}
...
See the JavaDoc for AtomicBoolean to grok what is going on there (assuming it is available in Android's Java).
Wrap everything in outerMethod that you want to run only once in a synchronized block:
private void outerMethod() {
synchronized (this) {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
}
That way, the first time the method is called, only one thread will be allowed into the synchronized block at a time. The first one will execute the code in the if statement, then set outerMethodHasBeenCalled to true. The other threads will see that it is true, and skip the if code.

How do i get returned value from inner Thread Runnable method in Java?

How do i assign Status with CallMe() using isFinish() to have returned value true?
public static boolean isFinish ()
{
boolean Status = false;
new Thread(new Runnable()
{
public void run()
{
/* This shell return true or false
* How do you keep it in Status
*/
CallMe();
}
}).start();
/* How can i get the true or false exactly from CallMe? here */
return Status;
}
public static boolean CallMe()
{
/* some heavy loads ... */
return true;
}
There are two ways of doing this.
The first is to use a future computation result and the other is to have a shared variable.
I think that the first method is much cleaner than the second, but sometimes you need to push values to the thread too.
Using a RunnableFuture.
FutureTask implements a RunnableFuture. So you create that task which, once executed, will have a value.
RunnableFuture f = new FutureTask(new Callable<Boolean>() {
// implement call
});
// start the thread to execute it (you may also use an Executor)
new Thread(f).start();
// get the result
f.get();
Using a holder class
You create a class holding a value and share a reference to that class. You may create your own class or simply use the AtomicReference.
By holder class, I mean a class that has a public modifiable attribute.
// create the shared variable
final AtomicBoolean b = new AtomicBoolean();
// create your thread
Thread t = new Thread(new Runnable() {
public void run() {
// you can use b in here
}
});
t.start();
// wait for the thread
t.join();
b.get();
You rewrite the code to use Callable<Boolean> and obtain a Future when launching the Runnable.
Futures allow the launching thread to properly check that the value is ready and read it asynchronously. You could do the coding by hand, but since Future is now part of the standard JVM libraries, why would you (outside of a programming class)?
Working with raw threads, you could implement Runnable with a named type, and store the value in it.
class MyRunnable implements Runnable {
boolean status;
public void run() {
...
}
}
However, if you're working with another thread, you'll have to synchronize in some way.
It would be easier to use the higher-level tools provided by the java.util.concurrent hierarchy. You can submit a Callable to an Executor, and get a Future. You can ask the Future if it's done, and get the result. There's an Oracle tutorial here.

Categories