Reputation: 2857
I've come across this particular scenario many times, and I wonder what's the "clean" way of solving it. It all comes to this: how can I store a reference to an object that's being set in a different Thread?
Let me illustrate this with an example, imagine I have a class named Bar, and objects from this class are retrieved from this method:
public class BarBuilder {
public static void buildNewBar(final BarListener listener) {
// This could be an HTTP request or something that can only be done in a
// different thread
new Thread(new Runnable() {
@Override
public void run() {
listener.onNewBar(new Bar());
}
}).start();
}
}
The important part here is that buildNewBar() method has to be executed in another Thread, so instead of returning the value, it will communicate the result through a listener. This is quite common for operations that need HTTP requests or any sort of connection.
Now, my problem is if I need the value before continuing execution, how can I access to it? I can lock a thread with a semaphore until I have my value, but the storing of the value is what I don't have clear (If I declare a final variable, it cannot be set again). I solved it creating a new class which I named "Pointer", but I wonder why there isn't any built in java class to do this (I used Vector before, but it doesn't seem like a good solution either).
public Bar getBar() {
final Pointer<Bar> barPointer = new Pointer<Bar>();
final Semaphore semaphore = new Semaphore(0);
BarBuilder.buildNewBar(new BarListener() {
@Override
public void onNewBar(Bar bar) {
barPointer.set(bar);
semaphore.release();
}
});
semaphore.acquireUninterruptibly();
// Now I have my value
return barPointer.get();
}
public class Pointer<T> {
T object;
public void set(T object) {
this.object = object;
}
public T get() {
return object;
}
}
Let's see if there is a better way of doing this supported by Java language, I have seen classes like Reference, but it seems like their purpose is something different and setters don't exist (they are read-only), so that doesn't solve my issues either.
Upvotes: 0
Views: 85
Reputation: 53694
public Bar getBar() {
final BarPointer barPointer = new BarPointer().
BarBuilder.buildNewBar(barPointer);
return barPointer.get();
}
public class BarPointer extends FutureTask<Bar> implements BarListener {
@Override
public void onNewBar(Bar bar) {
set(bar);
}
}
Upvotes: 2
Reputation: 1927
In order to eliminate the need to write a custom Pointer class, I would simply use AtomicReference.
Upvotes: 0