Dave Maple
Dave Maple

Reputation: 8402

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+.

Upvotes: 10

Views: 8703

Answers (3)

BalusC
BalusC

Reputation: 1108567

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.

Upvotes: 19

Voo
Voo

Reputation: 30206

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)

Upvotes: 3

Ferguzz
Ferguzz

Reputation: 6077

Why not just

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

Upvotes: 0

Related Questions