I created a singleton to have a unique instance of ExecutorService in my application.
I whould like to know which is the better of the two classes below.
First one :
public class ExecutorServiceSingleton {
private static final Logger LOG = LoggerFactory.getLogger(ExecutorServiceSingleton.class);
private ScheduledExecutorService scheduledExecutorService;
private static ExecutorServiceSingleton instance;
private ExecutorServiceSingleton() {
scheduledExecutorService = Executors.newScheduledThreadPool(1);
}
/**
* Method to run the task
*/
public void runTask(Runnable task) {
scheduledExecutorService.submit(task);
}
/**
* Get the instance : If the instance is null, then we return a new one. If the instance is diff than null, then, we use the instance value and we return it.
*
* @return the instance
*/
public static ExecutorServiceSingleton getInstance() {
if (instance == null) {
instance = new ExecutorServiceSingleton();
}
LOG.info("Instance: " + instance);
return instance;
}
}
Second one :
public class ExecutorServiceSingleton {
private static final Logger LOG = LoggerFactory.getLogger(ExecutorServiceSingleton.class);
private ScheduledExecutorService scheduledExecutorService;
private volatile static ExecutorServiceSingleton instance;
private ExecutorServiceSingleton() {
scheduledExecutorService = Executors.newScheduledThreadPool(1);
}
/**
* Method to run the task
*/
public void runTask(Runnable task) {
scheduledExecutorService.submit(task);
}
/**
* Get the instance : If the instance is null, then we return a new one. If the instance is diff than null, then, we use the instance value and we return it.
*
* @return the instance
*/
public static ExecutorServiceSingleton getInstance() {
if (instance == null) {
synchronized (ExecutorServiceSingleton.class) {
if (instance == null) {
instance = new ExecutorServiceSingleton();
}
}
}
LOG.info("Instance: " + instance);
return instance;
}
}
1 Answer 1
The memory model of the jvm doesn't allow double checked locking like that to work like you think it does. The jvm is allowed to assign the object before running the constructor.
In java class loading is already lazy and perfectly thread safe. So the naive
private static final ExecutorServiceSingleton instance = new ExecutorServiceSingleton();
is fine for most purposes.
If you really want the lazy ness to go further then something like:
private static class Nested{
private static final ExecutorServiceSingleton instance = new ExecutorServiceSingleton();
}
public static ExecutorServiceSingleton getInstance() {
return Nested.instance;
}
will do what you need.
-
\$\begingroup\$ Thanks for your help. Your first one is not a solution for me, I don't want to instanciate it at the JVM, I want to instanciate it ONLY when I need. Why your second solution is better than my first one? \$\endgroup\$Eloise– Eloise2017年11月17日 13:15:21 +00:00Commented Nov 17, 2017 at 13:15
-
1\$\begingroup\$ Because the
Nested
class will only get loaded whengetInstance
is called and requiresNested
's static member. A feature of the jvm's lazy class loading. \$\endgroup\$ratchet freak– ratchet freak2017年11月17日 13:18:56 +00:00Commented Nov 17, 2017 at 13:18 -
\$\begingroup\$ @Bob why do you think you need it to "ONLY" be instantiated when you need it? I don't think that the "cost" of one Executor service at startup is worth fussing over... \$\endgroup\$Vogel612– Vogel6122017年11月17日 14:26:20 +00:00Commented Nov 17, 2017 at 14:26
-
\$\begingroup\$ @Vogel612 Because my mentor refused my code for this reason... That's why I'm asking myself about the best solution! Not sure he's right for that even if the project is big \$\endgroup\$Eloise– Eloise2017年11月17日 14:32:58 +00:00Commented Nov 17, 2017 at 14:32
-
1\$\begingroup\$ @Bob But the java virtual machine will only load a class when one of its methods is called (including creating on object of the type) or when a field of is accessed. \$\endgroup\$ratchet freak– ratchet freak2017年11月17日 14:43:26 +00:00Commented Nov 17, 2017 at 14:43
Explore related questions
See similar questions with these tags.
final static
guarantees in the first place. \$\endgroup\$