First let's look at the utility class (most javadoc has been removed to simply the example):
public class ApplicationContextUtils {
/**
* The application context; care should be taken to ensure that 1) this
* variable is assigned exactly once (in the
* {#link #setContext(ApplicationContext)} method, 2) the context is never
* reassigned to {#code null}, 3) access to the field is thread-safe (no race
* conditions can occur)
*/
private static ApplicationContext context = null;
public static ApplicationContext getContext() {
if (!isInitialized()) {
throw new IllegalStateException(
"Context not initialized yet! (Has the "
+ "ApplicationContextProviderBean definition been configured "
+ "properly and has the web application finished "
+ "loading before you invoked this method?)");
}
return context;
}
public static boolean isInitialized() {
return context == null;
}
#SuppressWarnings("unchecked")
public static <T> T getBean(final String name, final Class<T> requiredType) {
if (requiredType == null) {
throw new IllegalArgumentException("requiredType is null");
}
return (T) getContext().getBean(name, requiredType);
}
static synchronized void setContext(final ApplicationContext theContext) {
if (theContext == null) {
throw new IllegalArgumentException("theContext is null");
}
if (context != null) {
throw new IllegalStateException(
"ApplicationContext already initialized: it cannot be done twice!");
}
context = theContext;
}
private ApplicationContextUtils() {
throw new AssertionError(); // NON-INSTANTIABLE UTILITY CLASS
}
}
Finally, there is the following helper Spring managed bean that actually calls the 'setContext' method:
public final class ApplicationContextProviderBean implements
ApplicationContextAware {
public void setApplicationContext(
final ApplicationContext applicationContext) throws BeansException {
ApplicationContextUtils.setContext(applicationContext);
}
}
Spring will call the setApplicationContext method once after the app is started. Assuming a nincompoop has not previously called ApplicationContextUtils.setContext(), that should lock in the reference to the context in the utility class, allowing calls to getContext() to success (meaning that isInitialized() returns true).
I just want to know if this class violates any principles of good coding practices, with respect to thread safety in particular (but other stupidities found are welcome).
Thanks for helping me to become a better programmer, StackOverflow!
Regards,
LES
P.S. I didn't go into why I need this utility class - let it suffice that I indeed do have a legitimate need to access it from a static context anywhere in the application (after the spring context has loaded, of course).
No. It's not thread safe.
Writes to the context class variable are not guaranteed to be visible to threads that read that variable through getContext().
At the very least, declare context to be volatile. Ideally, redefine context as an AtomicReference, set through a call like this:
if(!context.compareAndSet(null, theContext))
throw new IllegalStateException("The context is already set.");
Here's a more complete example:
public class ApplicationContextUtils {
private static final AtomicReference<ApplicationContext> context =
new AtomicReference<ApplicationContext>();
public static ApplicationContext getContext() {
ApplicationContext ctx = context.get();
if (ctx == null)
throw new IllegalStateException();
return ctx;
}
public static boolean isInitialized() {
return context.get() == null;
}
static void setContext(final ApplicationContext ctx) {
if (ctx == null)
throw new IllegalArgumentException();
if (!context.compareAndSet(null, ctx))
throw new IllegalStateException();
}
public static <T> T getBean(final String name, final Class<T> type) {
if (type == null)
throw new IllegalArgumentException();
return type.cast(getContext().getBean(name, type));
}
private ApplicationContextUtils() {
throw new AssertionError();
}
}
Note that in addition to thread safety, this also provides type safety, taking advantage of the Class instance passed into the getBean() method.
I'm not sure how you plan to use the isInitialized() method; it doesn't seem very useful to me, since as soon as you call it, the condition could change, and you don't have a good way to be notified.
Spring already has a class called ContextSingletonBeanFactoryLocator that wires up static access to the ApplicationContext for you. At the least, using this class might save you the trouble of having to worry about if your custom approach is thread safe.
However it's a little confusing to use this class at first, since there's a little bit of indirection going on. You can take a look at this blog post for more information on how this call works.
Related
This is a job interview question.
Implement the singleton pattern with a twist. First, instead of
storing one instance, store two instances. And in every even call of
getInstance(), return the first instance and in every odd call of
getInstance(), return the second instance.
My implementation is as follows:
public final class Singleton implements Cloneable, Serializable {
private static final long serialVersionUID = 42L;
private static Singleton evenInstance;
private static Singleton oddInstance;
private static AtomicInteger counter = new AtomicInteger(1);
private Singleton() {
// Safeguard against reflection
if (evenInstance != null || oddInstance != null) {
throw new RuntimeException("Use getInstance() instead");
}
}
public static Singleton getInstance() {
boolean even = counter.getAndIncrement() % 2 == 0;
// Make thread safe
if (even && evenInstance == null) {
synchronized (Singleton.class) {
if (evenInstance == null) {
evenInstance = new Singleton();
}
}
} else if (!even && oddInstance == null) {
synchronized (Singleton.class) {
if (oddInstance == null) {
oddInstance = new Singleton();
}
}
}
return even ? evenInstance : oddInstance;
}
// Make singleton from deserializaion
protected Singleton readResolve() {
return getInstance();
}
#Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Use getInstance() instead");
}
}
Do you see a problem? The first call may enter getInstance and the thread get preempted. The second call may then enter getInstance but will get the oddInstance instead of the evenInstance.
Obviously, this can be prevented by making getInstance synchronized, but it's unnecessary. The synchronization is only required twice in the lifecycle of the singleton, not for every single getInstance call.
Ideas?
Most importantly, the evenInstance and oddInstance variables need to be declared volatile. See the famous "Double-Checked Locking is Broken" declaration: https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Also, you should really use different objects in the synchronization blocks for the even and odd instances so they can be constructed simultaneously.
Finally, the check in the Singleton constructor is broken and will throw an exception in the second call to getInstance()
Other than that it's fine, but it's better if you don't do the concurrency work yourself:
public final class Singleton implements Cloneable, Serializable {
private static AtomicInteger counter = new AtomicInteger(1);
public static Singleton getInstance() {
if (counter.getAndIncrement() % 2 == 0) {
return EvenHelper.instance;
} else {
return OddHelper.instance;
}
}
private static class EvenHelper {
//not initialized until the class is used in getInstance()
static Singleton instance = new Singleton();
}
private static class OddHelper {
//not initialized until the class is used in getInstance()
static Singleton instance = new Singleton();
}
}
You don't say the singleton must be lazily initialized, so I'll assume not...
You could be over-thinking it. Try this:
public final class Singleton implements Cloneable, Serializable {
private static Singleton[] instances = new Singleton[]{new Singleton(), new Singleton()};
private static AtomicInteger counter = new AtomicInteger();
private Singleton() {} // further protection not necessary
public static Singleton getInstance() {
return instances[counter.getAndIncrement() % 2];
}
// Make singleton from deserializaion
protected Singleton readResolve() {
return getInstance();
}
#Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Use getInstance() instead");
}
}
If you're worried about reflection attacks, just use an enum, which is bullet-proof, something like:
public final class Singleton implements Cloneable, Serializable {
private static AtomicInteger counter = new AtomicInteger();
private enum SingletonInstance implements Cloneable, Serializable {
ODD, EVEN;
private Singleton instance = new Singleton();
}
private Singleton() {} // further protection not necessary
public static Singleton getInstance() {
return SingletonInstance.values()[counter.getAndIncrement() % 2].instance;
}
// Make singleton from deserializaion
protected Singleton readResolve() {
return getInstance();
}
}
Do you see a problem? The first call may enter getInstance and the thread get preempted. The second call may then enter getInstance but will get the oddInstance instead of the evenInstance.
Obviously, this can be prevented by making getInstance synchronized, but it's unnecessary. The synchronization is only required twice in the lifecycle of the singleton, not for every single getInstance call.
If you really want to "fix" this "problem", your only option is to synchronize getInstance. But how would one really see this problem? What if the first thread is preempted right after getInstance?
In multithreading, the absolute order of events is not completely deterministic. So you always have the risk that actions seem to be out-of-order.
btw: The against the "reflection attack" has a serious flaw! It prevents the construction of evenInstance! I guess you should change || to &&. But that still doesn't give you any guarantees, because the "reflection attack" could be between the first and second call. You have to preconstruct both instances at class loading time to be 99% sure.
And if you're worried about it, you should definitely implement neither Cloneable nor Serializable!
Suppose I declare like this:
private static Boolean isCondition = false;
Then I am using this like below in synchronized statement:
synchronized(isCondition){
isCondition = true;
somestuff();
}
Here my question is if I update isCondition then it will get a new reference due to autoboxing and if new thread will come in synchronized block then they will get lock on new object enter into synchronized block. This I dont want to happen.
So please suggest me alternatives and if I use volatile then how exactly it will prevent this like below:
private static volatile Boolean isCondition = false;
The actual code is like that:
package com.test.spring.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* #author Pratik
*/
public class TouchPointsSpringContext implements ApplicationContextAware
{
private static final Log g_log = LogFactory.getLog(TouchPointsSpringContext.class);
private static ApplicationContext CONTEXT;
private static volatile Boolean isServiceInitialized = false;
/**
* This method is called from within the ApplicationContext once it is done
* starting up, it will stick a reference to itself into this bean.
*
* #param context
* a reference to the ApplicationContext.
*/
public void setApplicationContext(ApplicationContext context) throws BeansException
{
CONTEXT = context;
}
private static void initializeTouchPointService()
{
g_log.info("getting touchpoints service application context");
String[] locations =
{ "appContext-main.xml", "appContext-hibernate.xml" };
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(locations);
g_log.info("setting touchpoints service application context");
CONTEXT = applicationContext;
}
/**
* This is about the same as context.getBean("beanName"), except it has its
* own static handle to the Spring context, so calling this method
* statically will give access to the beans by name in the Spring
* application context. As in the context.getBean("beanName") call, the
* caller must cast to the appropriate target class. If the bean does not
* exist, then a Runtime error will be thrown.
*
* #param beanName
* the name of the bean to get.
* #return an Object reference to the named bean.
*/
public static Object getBean(String beanName)
{
if (!isServiceInitialized || (CONTEXT == null))
{
synchronized (isServiceInitialized)
{
if (!isServiceInitialized)
{
initializeTouchPointService();
isServiceInitialized = true;
}
}
}
return CONTEXT.getBean(beanName);
}
public static void main(String[] args)
{
TouchPointsSpringContext.getBean("lookupService");
}
}
Using a Boolean as a lock is a very bad idea: you are effectively using a global variable Boolean.TRUE/FALSE which any other parts of your code can access and potentially deadlock your code.
And using a non final variable as a lock is an even worse idea: everytime you reallocate the instance (isCondition = true) you change your lock, meaning that two threads may execute your synchronized block concurrently, which kind of defeats the whole idea.
So I would recommend a standard idiom:
private static final Object lock = new Object();
private static boolean isCondition;
synchronised(lock) {
isCondition = true;
// ...
}
I think most of the other answers here are not completely right. It is a little bit difficult to understand what you are doing because you do not include the code for initializeTouchPointService, however you appear to be doing something which is a variation on the "Double Checked Locking" idiom.
It is difficult to get this concurrency idiom right and if you are using a version of Java before 5, then you should not attempt to use this idiom at all. I will assume you are using Java 5+.
The important parts of your code are:
private static ApplicationContext CONTEXT;
private static volatile Boolean isServiceInitialized = false;
...
if (!isServiceInitialized || (CONTEXT == null))
{
synchronized (isServiceInitialized)
{
if (!isServiceInitialized)
{
initializeTouchPointService();
isServiceInitialized = true;
}
}
}
Assuming that you are using Java 5 or above, you must use volatile on all relevant variables to get this idiom to work correctly. You must also re-check the full condition inside the synchronized block.
You must not use a Boolean as your lock, since Boolean objects are immutable you will get a different object when you change the condition from false to true. Instead use a separate lock object and boolean primitive for the condition.
private final Object lock = new Object();
private volatile boolean isServiceInitialized;
private volatile ApplicationContext context;
public Object getBean(String beanName) {
if (!isServiceInitialized || context == null) {
synchronized(lock) {
if (!isServiceInitialized || context == null) {
initializeTouchPointService();
isServiceInitialized = true;
}
}
}
return CONTEXT.getBean(beanName);
}
However, locks in recent versions of Java have very good performance on most architectures. So using the double-checked locking idiom may not make your program much faster - especially compared to how slow spring reflection will be when calling getBean.
Instead of your double-checked design, how about the following simpler design which also avoids volatile:
private final Object lock = new Object();
private boolean isServiceInitialized;
private ApplicationContext context;
private ApplicationContext context() {
synchronized(lock) {
if (!isServiceInitialized || context == null) {
initializeTouchPointService();
condition = true;
}
return context;
}
}
public Object getBean(String beanName) {
return context().getBean(beanName);
}
I also recommend avoiding the use of static where ever possible, as writing unit tests in the presence of global variables can be tricky. I would seriously consider if there is any way you can change your design to reduce or eliminate your use of static state.
============ edit
Based on my best guess of what the OP is trying to achieve, perhaps this would be better. However, it removes the lazy initialisation. So if you program sometimes refers to this TouchPointsSpringContext class without using the getBean() method then you don't want this answer.
public class TouchPointsSpringContext
{
private static final Log g_log = LogFactory.getLog(TouchPointsSpringContext.class);
private static ApplicationContext CONTEXT = initializeTouchPointService();
private static ApplicationContext initializeTouchPointService()
{
g_log.info("getting touchpoints service application context");
String[] locations =
{ "appContext-main.xml", "appContext-hibernate.xml" };
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(locations);
g_log.info("setting touchpoints service application context");
return applicationContext;
}
public static Object getBean(String beanName)
{
return CONTEXT.getBean(beanName);
}
public static void main(String[] args)
{
TouchPointsSpringContext.getBean("lookupService");
}
}
Note that the JVM will automatically make sure that your static CONTEXT gets initalised exactly once.
Or alternatively, if you can avoid implementing "ApplicationContextAware" (implementing it seems unnecessary given the rest of the code), but you need to keep he lazy initialisation, then this might be better:
public class TouchPointsSpringContext
{
private static final Log g_log = LogFactory.getLog(TouchPointsSpringContext.class);
private static volatile ApplicationContext CONTEXT;
private static final Object lock = new Object();
private static ApplicationContext initializeTouchPointService()
{
g_log.info("getting touchpoints service application context");
String[] locations =
{ "appContext-main.xml", "appContext-hibernate.xml" };
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(locations);
g_log.info("setting touchpoints service application context");
return applicationContext;
}
public static Object getBean(String beanName)
{
if (CONTEXT == null)
{
synchronized (lock)
{
if (CONTEXT == null)
{
CONTEXT = initializeTouchPointService();
}
}
}
return CONTEXT.getBean(beanName);
}
public static void main(String[] args)
{
TouchPointsSpringContext.getBean("lookupService");
}
}
Not a full answer, but: Several people here said things like "You must not use Boolean as a lock because..."
Those explanations complicate what should be a simple idea. When you write synchronized (foo) { ... }, you are not synchronizing on the variable foo, you are synchronizing on some object that is the result of the expression, foo.
You did something like this in your example:
Boolean isCondition = ...;
synchronized(isCondition) {
isCondition = true;
...
}
When a thread enters that synchronized block, it acquires the monitor for a particular instance of the Boolean class. Then, the next thing that it does is assign isCondition. The same variable now points to a different instance.
When a second thread tries to enter the same block, it will attempt to synchronize on the new instance, and it will succeed even if the first thread still is in the block. The only thing that synchronized prevents is, it prevents two different threads from synchronizing on the same instance at the same time. In your example, the two different threads synchronized on two different instances, and that is allowed.
Never do this:
synchronized ( foo ) {
...
foo = ...;
...
}
A good practice is, if you are going to put a simple variable name in the parens (and that's by far the most common use-case), then make it a final variable.
final MyThingummie myThingummie = new MyThingummie(...);
synchronized ( myThingummie ) {
...
}
As some others have suggested in comments, you could synchronize on something else and avoid this problem.
Define a new variable to lock on:
private final Object lock;
Now change your code a bit:
synchronized(lock) {
isCondition = true;
somestuff();
}
You can also achieve similar functionality without the variable by having all of this in a synchronized method.
I have the following code in the mClass constructor:
public mClass(Context ctx) {
super();
this.ctx = ctx;
}
The context can't be null because its necesary for the object operation. So if I allow the creation of an new mClass(null) it will break later.
I'd like to crash when the object is create because is when the incorrect situation is happening. Whats the standard way of doing this?
For example making
public mClass(Context ctx) {
super();
if(ctx==null) throw new Exception ("....");
this.ctx = ctx;
}
forces to declare the method as exception thrower and I dont wan't to do this because passing a null value is not usual
Throw java.lang.IllegalArgumentException,
which is a runtime exception so you don't need to forcibly handle this, and if it is thrown application will get crashed (if it is not handled)
You can avoid throwing an exception from the constructor all together by making your class' constructor private thereby ensuring clients can only create instances of your class via a builder. The builder can check the validity of the supplied constructor dependencies before constructing an object as shown below:
public class MyClass {
public static class MyClassBuilder {
private Context ctx;
public MyClassBuilder setContext(Context ctx) {
this.ctx = ctx;
return this;
}
public MyClass build() {
if(ctx==null) {
throw new IllegalArgumentException ("");
} else {
return new MyClass(this.ctx);
}
}
}
private final Context ctx;
private MyClass(Context ctx) {
super();
this.ctx = ctx;
}
}
If MyClass cannot be responsible for constructing its own Context you should inject it like you do. Throwing a RuntimeException or any subclass will do for a null-check, but IllegalArgumentException is most appropriate here.
Do not forget to make the ctx field final, it will make your code more robust.
I have a class that might throw any run-time exceptions during initialization. I want the class to be a singleton since the cost of keeping several objects in memory is high. I am using that class in another class.
My use case is as follows:
I have to use a single instance of Controller.
Each instance of Parent must use the same Controller instance.
Controller
constructor might throw exceptions.
If instantiation fails, I should
retry to instantiate after sometime.
So I check if my Controller instance is null when I try to do a "get" on the Controller, if yes, I try to instantiate it again.
Following is my code:
class Parent
{
private static volatile Controller controller;
private static final Object lock = new Object();
static
{
try
{
controller = new Controller();
}
catch(Exception ex)
{
controller = null;
}
}
private Controller getController() throws ControllerInstantiationException
{
if(controller == null)
{
synchronized(lock)
{
if(controller == null)
{
try
{
controller = new Controller();
}
catch(Exception ex)
{
controller = null;
throw new ControllerInstatntationException(ex);
}
}
}
}
return controller;
}
//other methods that uses getController()
}
My question is, is this code broken? I read somewhere that the above code would be a problem in JVM 1.4 or earlier. Can you provide references/solutions? Please note that I am asking this question because there is a lot of confusion regarding this topic in the internet.
Thanks.
I believe it's not broken, cause of volatile declaration. But imho better to avoid code like this. There is no guarantee, that this code will work with Java 8 for example. There are another way to create lazy singleton. I always (almost) use this method. First time faced with it in Java Concurrency in Practice book.
public class Singleton {
private Singleton() { }
private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
I don't know what you are doing in your code, it's hard to say, how to tweak it. The most straightforward way, simply use synchronize method. Do you seriously want to receive some performance benefit using double-check-locking ? Is there bottle-neck in synch method ?
The only thing which is broken is to make the example far more complicated than it needs to be.
All you need is an enum
// a simple lazy loaded, thread safe singleton.
enum Controller {
INSTANCE
}
Using an AtomicBoolean (much like I suggested here) would be safer and allows for repeat attempts at instantiation on failure.
public static class ControllerFactory {
// AtomicBolean defaults to the value false.
private static final AtomicBoolean creatingController = new AtomicBoolean();
private static volatile Controller controller = null;
// NB: This can return null if the Controller fails to instantiate or is in the process of instantiation by another thread.
public static Controller getController() throws ControllerInstantiationException {
if (controller == null) {
// Stop another thread creating it while I do.
if (creatingController.compareAndSet(false, true)) {
try {
// Can fail.
controller = new Controller();
} catch (Exception ex) {
// Failed init. Leave it at null so we try again next time.
controller = null;
throw new ControllerInstantiationException(ex);
} finally {
// Not initialising any more.
creatingController.set(false);
}
} else {
// Already in progress.
throw new ControllerInstantiationException("Controller creation in progress by another thread.");
}
}
return controller;
}
public static class ControllerInstantiationException extends Exception {
final Exception cause;
public ControllerInstantiationException(Exception cause) {
this.cause = cause;
}
public ControllerInstantiationException(String cause) {
this.cause = new Exception(cause);
}
}
public static class Controller {
private Controller() {
}
}
}
Yes, it is guaranteed to work by the Java Memory Model on modern JVMs. See the section Under the new Java Memory Model in The "Double-Checked Locking is Broken" Declaration.
As other answers have pointed out, there are simpler singleton patterns, using Holder classes or enums. However, in cases like yours, where you want to allow for trying to reinitialize several times if the first try fails, I believe that double-checked locking with a volatile instance variable is fine.
It is not an answer to your question but this famous article on Double-Checked Locking is Broken explains well as to why it is broken for java 1.4 or earlier version.
What are some recommended approaches to achieving thread-safe lazy initialization? For instance,
// Not thread-safe
public Foo getInstance(){
if(INSTANCE == null){
INSTANCE = new Foo();
}
return INSTANCE;
}
For singletons there is an elegant solution by delegating the task to the JVM code for static initialization.
public class Something {
private Something() {
}
private static class LazyHolder {
public static final Something INSTANCE = new Something();
}
public static Something getInstance() {
return LazyHolder.INSTANCE;
}
}
see
http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
and this blog post of Crazy Bob Lee
http://blog.crazybob.org/2007/01/lazy-loading-singletons.html
If you're using Apache Commons Lang, then you can use one of the variations of ConcurrentInitializer like LazyInitializer.
Example:
ConcurrentInitializer<Foo> lazyInitializer = new LazyInitializer<Foo>() {
#Override
protected Foo initialize() throws ConcurrentException {
return new Foo();
}
};
You can now safely get Foo (gets initialized only once):
Foo instance = lazyInitializer.get();
If you're using Google's Guava:
Supplier<Foo> fooSupplier = Suppliers.memoize(new Supplier<Foo>() {
public Foo get() {
return new Foo();
}
});
Then call it by Foo f = fooSupplier.get();
From Suppliers.memoize javadoc:
Returns a supplier which caches the instance retrieved during the first call to get() and returns that value on subsequent calls to get(). The returned supplier is thread-safe. The delegate's get() method will be invoked at most once. If delegate is an instance created by an earlier call to memoize, it is returned directly.
This can be done in lock-free manner by using AtomicReference as instance holder:
// in class declaration
private AtomicReference<Foo> instance = new AtomicReference<>(null);
public Foo getInstance() {
Foo foo = instance.get();
if (foo == null) {
foo = new Foo(); // create and initialize actual instance
if (instance.compareAndSet(null, foo)) // CAS succeeded
return foo;
else // CAS failed: other thread set an object
return instance.get();
} else {
return foo;
}
}
Main disadvantage here is that multiple threads can concurrently instantiate two or more Foo objects, and only one will be lucky to be set up, so if instantiation requires I/O or another shared resource, this method may not be suitable.
At the other side, this approach is lock-free and wait-free: if one thread which first entered this method is stuck, it won't affect execution of others.
The easiest way is to use a static inner holder class :
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
}
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
This is called double checking!
Check this http://jeremymanson.blogspot.com/2008/05/double-checked-locking.html
If you use lombok in your project, you can use a feature described here.
You just create a field, annotate it with #Getter(lazy=true) and add initialization, like this:
#Getter(lazy=true)
private final Foo instance = new Foo();
You'll have to reference field only with getter (see notes in lombok docs), but in most cases that's what we need.
Here is one more approach which is based on one-time-executor semantic.
The full solution with bunch of usage examples can be found on github (https://github.com/ManasjyotiSharma/java_lazy_init). Here is the crux of it:
“One Time Executor” semantic as the name suggests has below properties:
A wrapper object which wraps a function F. In current context F is a function/lambda expression which holds the initialization/de-initialization code.
The wrapper provides an execute method which behaves as:
Calls the function F the first time execute is called and caches the output of F.
If 2 or more threads call execute concurrently, only one “gets in” and the others block till the one which “got in” is done.
For all other/future invocations of execute, it does not call F rather simply returns the previously cached output.
The cached output can be safely accessed from outside of the initialization context.
This can be used for initialization as well as non-idempotent de-initialization too.
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
/**
* When execute is called, it is guaranteed that the input function will be applied exactly once.
* Further it's also guaranteed that execute will return only when the input function was applied
* by the calling thread or some other thread OR if the calling thread is interrupted.
*/
public class OneTimeExecutor<T, R> {
private final Function<T, R> function;
private final AtomicBoolean preGuard;
private final CountDownLatch postGuard;
private final AtomicReference<R> value;
public OneTimeExecutor(Function<T, R> function) {
Objects.requireNonNull(function, "function cannot be null");
this.function = function;
this.preGuard = new AtomicBoolean(false);
this.postGuard = new CountDownLatch(1);
this.value = new AtomicReference<R>();
}
public R execute(T input) throws InterruptedException {
if (preGuard.compareAndSet(false, true)) {
try {
value.set(function.apply(input));
} finally {
postGuard.countDown();
}
} else if (postGuard.getCount() != 0) {
postGuard.await();
}
return value();
}
public boolean executed() {
return (preGuard.get() && postGuard.getCount() == 0);
}
public R value() {
return value.get();
}
}
Here is a sample usage:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
/*
* For the sake of this example, assume that creating a PrintWriter is a costly operation and we'd want to lazily initialize it.
* Further assume that the cleanup/close implementation is non-idempotent. In other words, just like initialization, the
* de-initialization should also happen once and only once.
*/
public class NonSingletonSampleB {
private final OneTimeExecutor<File, PrintWriter> initializer = new OneTimeExecutor<>(
(File configFile) -> {
try {
FileOutputStream fos = new FileOutputStream(configFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw);
return pw;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
);
private final OneTimeExecutor<Void, Void> deinitializer = new OneTimeExecutor<>(
(Void v) -> {
if (initializer.executed() && null != initializer.value()) {
initializer.value().close();
}
return null;
}
);
private final File file;
public NonSingletonSampleB(File file) {
this.file = file;
}
public void doSomething() throws Exception {
// Create one-and-only-one instance of PrintWriter only when someone calls doSomething().
PrintWriter pw = initializer.execute(file);
// Application logic goes here, say write something to the file using the PrintWriter.
}
public void close() throws Exception {
// non-idempotent close, the de-initialization lambda is invoked only once.
deinitializer.execute(null);
}
}
For few more examples (e.g. singleton initialization which requires some data available only at run-time thus unable to instantiate it in a static block) please refer to the github link mentioned above.
Thinking about lazy initialization, I would expect getting a "almost real" object that just decorates the still not initialized object.
When the first method is being invoked, the instance within the decorated interface will be initialized.
* Because of the Proxy usage, the initiated object must implement the passed interface.
* The difference from other solutions is the encapsulation of the initiation from the usage. You start working directly with DataSource as if it was initialized. It will be initialized on the first method's invocation.
Usage:
DataSource ds = LazyLoadDecorator.create(dsSupplier, DataSource.class)
Behind the scenes:
public class LazyLoadDecorator<T> implements InvocationHandler {
private final Object syncLock = new Object();
protected volatile T inner;
private Supplier<T> supplier;
private LazyLoadDecorator(Supplier<T> supplier) {
this.supplier = supplier;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (inner == null) {
synchronized (syncLock) {
if (inner == null) {
inner = load();
}
}
}
return method.invoke(inner, args);
}
protected T load() {
return supplier.get();
}
#SuppressWarnings("unchecked")
public static <T> T create(Supplier<T> factory, Class<T> clazz) {
return (T) Proxy.newProxyInstance(LazyLoadDecorator.class.getClassLoader(),
new Class[] {clazz},
new LazyLoadDecorator<>(factory));
}
}
Put the code in a synchronized block with some suitable lock. There are some other highly specialist techniques, but I'd suggest avoiding those unless absolutely necessary.
Also you've used SHOUTY case, which tends to indicate a static but an instance method. If it is really static, I suggest you make sure it isn't in any way mutable. If it's just an expensive to create static immutable, then class loading is lazy anyway. You may want to move it to a different (possibly nested) class to delay creation to the absolute last possible moment.
Depending on what you try to achieve:
If you want all Threads to share the same instance, you can make the method synchronized. This will be sufficient
If you want to make a separate INSTANCE for each Thread, you should use java.lang.ThreadLocal
With Java 8 we can achieve lazy initialization with thread safety. If we have Holder class and it needs some heavy resources then we can lazy load the heavy resource like this.
public class Holder {
private Supplier<Heavy> heavy = () -> createAndCacheHeavy();
private synchronized Heavy createAndCacheHeavy() {
class HeavyFactory implements Supplier<Heavy> {
private final Heavy heavyInstance = new Heavy();
#Override
public Heavy get() {
return heavyInstance;
}
}
if (!HeavyFactory.class.isInstance(heavy)) {
heavy = new HeavyFactory();
}
return heavy.get();
}
public Heavy getHeavy() {
return heavy.get();
}
}
public class Heavy {
public Heavy() {
System.out.println("creating heavy");
}
}
Basing this answer on #Alexsalauyou's one I thought if it could be possible to implement a solution that does not call multiple instances.
In principle my solution may be a little bit slower (very very little), but it is definitely friendlier to the processor, and the garbage collector.
The idea is that you must first use a container which could hold an "int" value PLUS the generic you want to instance.
static class Container<T> {
final int i;
final T val;
//constructor here
}
Let this container's fields be final for concurrency purposes.
The LazyInit<T> class, must have an AtomicReference of this container.
AtomicReference<Container<T>> ref;
LazyInit must define phase processes as private static int constants:
private static final int NULL_PHASE = -1, CREATING_PHASE = 0, CREATED = 1;
private final Container<T> NULL = new Container<>(NULL_PHASE, null),
CREATING = new Container<>(CREATING_PHASE, null);
NULL and CREATING containers can be made static and upgraded to <?> to make things lighter, then one could grab them with a casting private static method.
The AtomicReference must be initialized as NULL:
private final AtomicReference<Container<T>> ref = new AtomicReference<>(getNull());
Finally the get() method would look like this:
#Override
public T get() {
Container<T> prev;
while ((prev = ref.get()).i < CREATED) {
if (ref.compareAndSet(getNull(), getCreating())) {
T res = builder.get();
ref.set(new Container<>(CREATED, res));
return res;
}
}
return prev.value;
}
Try to defined the method which gets an instance as synchronized:
public synchronized Foo getInstance(){
if(INSTANCE == null){
INSTANCE = new Foo();
}
return INSTANCE;
}
Or use a variable:
private static final String LOCK = "LOCK";
public synchronized Foo getInstance(){
synchronized(LOCK){
if(INSTANCE == null){
INSTANCE = new Foo();
}
}
return INSTANCE;
}