1
\$\begingroup\$

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;
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ neither... make it a static final. You're just opening yourself up to critique and subtle multithreading bugs using actual singletons. In the vast majority of cases, Singleton is just a fancy word for "Global Single Instance", which is exactly what final static guarantees in the first place. \$\endgroup\$
    – Vogel612
    Commented Nov 17, 2017 at 14:24

1 Answer 1

1
\$\begingroup\$

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.

\$\endgroup\$
8
  • \$\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
    Commented Nov 17, 2017 at 13:15
  • 1
    \$\begingroup\$ Because the Nested class will only get loaded when getInstance is called and requires Nested's static member. A feature of the jvm's lazy class loading. \$\endgroup\$ Commented 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
    Commented 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
    Commented 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\$ Commented Nov 17, 2017 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.