3

I am trying to create a threadsafe singleton class based on Initialization-on-demand holder idiom . Here is my code

public class Check{ 
  private Check(){  }
  private static class Provider {
    static final ExecutorService INSTANCE = new ThreadPoolExecutor(5, "read this val from file", 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());
  }
  public static ExecutorService getInstance() {
    return Provider.INSTANCE;
  }
}

My expectation is to initialize ExecutorService in a threadsafe manner and only one instance should be there (static).

Is this code achieving that - or are any changes required?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Steve
  • 33
  • 3
  • You might want to use the [enum based approach](https://stackoverflow.com/questions/12697726/how-to-initialize-java-enum-based-singleton) as it's the standard idiom these days (well, has been for years). – Kayaman Jul 10 '17 at 10:43
  • @Kayaman, generally speaking, enum approach also relies on locking by class loader, so I doubt there is much of a difference. – M. Prokhorov Jul 10 '17 at 10:45
  • 1
    @M.Prokhorov The difference is that using an enum is a cleaner approach and it's a standard idiom. It's not a bad idea to get used to using standard idioms. – Kayaman Jul 10 '17 at 10:46
  • @Kayaman holder class pattern is as much of an idiom as an enum, and I find that enum works way better for static instances of your own classes which you may declare as enums at will. – M. Prokhorov Jul 10 '17 at 10:51
  • @M.Prokhorov well, I'd guess that'll be pretty opinion based. – Kayaman Jul 10 '17 at 19:41
  • @Kayaman, yes, it is. The guidelines linked in accepted answer discuss both as valid conforming implementations of init-on-demand, and both even rely on same locking technique to achieve the goal, which I said from the start. Everything else is opinion, including "cleaniness" or what have you. – M. Prokhorov Jul 11 '17 at 08:21

2 Answers2

4

According to the SEI guidelines your approach is fine.

But since we have enums, the easy way to get that to use enums:

public enum Service {
  INSTANCE;

  private final ExecutorService service = ...
  public getService() { return service ; }

And if you want to be really smart, you also define an interface which that enum implements; because that allows you to later mock usages of that singleton. Which becomes extremely helpful for writing unit tests using a same-thread-exectution-service replacement.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • `Service.INSTANCE.getService()` can't really be mocked I'm pretty sure. And that'd be the most common use of the pattern. – M. Prokhorov Jul 11 '17 at 08:19
  • But a field of that the **interface** type can be. And that field can be initialized by calling that INSTANCE.getService() - or by providing a mocked object. – GhostCat Jul 11 '17 at 08:45
  • I've almost never seen examples of something expecting a factory and not being a factory itself. In this particular case it's easier to mock out `ExecutorService`, and classes expecting be given one, than to give dependents a factory which they should call a single defined method on. – M. Prokhorov Jul 11 '17 at 08:49
0

The most simplest thread-safe initialization is to use a static final class variable like this:

public class Check {
  public static final Executor EXECUTOR = new ThreadPoolExecutor(5, "read this val from file", 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());
  // ...
}

Add a Getter if you prefer that style.

What you are trying is a lazy initialization, which is best done with enums (as by GhostCat's answer). But for your use-case lazy initialization is not necessary, as the executor initializes fast and with low footprint.

TwoThe
  • 13,879
  • 6
  • 30
  • 54