Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory for Thread Safe Singleton in Java

This is a sample of the basic pattern I've been using for a Factory that returns a thread-safe Singleton:

public class UserServiceFactory {

    private volatile static UserService userService;

    private UserServiceFactory() { }

    public static UserService getInstance() {
        if (userService == null) {
            synchronized(UserServiceImpl.class) {            
                if (userService == null) {
                    userService = new UserServiceImpl();
                }        
            }
        }

        return userService;
    }

}

It uses both volatile and the double check idiom to ensure that a single instance is created and is visible across threads.

Is there a less verbose and/or less expensive way to accomplish the same goal in 1.6+.

like image 350
Dave Maple Avatar asked May 22 '11 13:05

Dave Maple


2 Answers

Use the Initialization On Demand Holder idiom, it's simpler and better readable:

public class UserServiceFactory {

    private UserServiceFactory () {}

    private static class UserServiceHolder {
        private static final UserService INSTANCE = new UserService();
    }

    public static UserService getInstance() {
        return UserServiceHolder.INSTANCE;
    }

}

However, I'd prefer Just Create One idiom.


Update: as your question history confirms, you're using Java EE. If your container supports it, you could also make it a @Singleton EJB and use @EJB to inject it (although @Stateless is preferable since @Singleton is by default read-locked).

@Singleton
public class UserService {}

with e.g. in a JSF managed bean

@EJB
private UserService userService;

This way you delegate the instantiation job to the container.

like image 165
BalusC Avatar answered Nov 01 '22 01:11

BalusC


You could let the class loader do its maigc and initialize the static variable at startup - this is guaranteed to work, because the classloader guarantees single threaded behavior.

If you want to initialize the instance lazily and mostly lockfree, then no, you have to do it this way and make sure you're using Java >= 1.5

Edit: See BalusC's solution that uses the classloader a bit more intelligently. Note that this all works because the classloader initializes classes lazily - ie they're only loaded at their first access - and because inner classes are handled just like normal classes in that regard (just because you load the outer class doesn't mean the inner class is loaded)

like image 24
Voo Avatar answered Nov 01 '22 01:11

Voo