Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

multithreading - Thread safe multitons in Java

Given the following multiton:

public class Multiton 
{
    private static final Multiton[] instances = new Multiton[...];

    private Multiton(...) 
    {
        //...
    }

    public static Multiton getInstance(int which) 
    {
        if(instances[which] == null) 
        {
            instances[which] = new Multiton(...);
        }

        return instances[which];
    }
}

How can we keep it thread safe and lazy without the expensive synchronization of the getInstance() method and the controversy of double-checked locking? An effective way for singletons is mentioned here but that doesn't seem to extend to multitons.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

UPDATE: with Java 8, it can be even simpler:

public class Multiton {
    private static final ConcurrentMap<String, Multiton> multitons = new ConcurrentHashMap<>();

    private final String key;
    private Multiton(String key) { this.key = key; }

    public static Multiton getInstance(final String key) {
        return multitons.computeIfAbsent(key, Multiton::new);
    }
}

Mmm that's good!


ORIGINAL ANSWER

This is a solution which builds on the Memoizer pattern as described in JCiP. It uses a ConcurrentHashMap like one of the other answers, but instead of storing the Multiton instances directly, which can lead to creating unused instances, it stores the computation that leads to the creation of the Multiton. That additional layer solves the problem of unused instances.

public class Multiton {

    private static final ConcurrentMap<Integer, Future<Multiton>> multitons = new ConcurrentHashMap<>();
    private static final Callable<Multiton> creator = new Callable<Multiton>() {
        public Multiton call() { return new Multiton(); }
    };

    private Multiton(Strnig key) {}

    public static Multiton getInstance(final Integer key) throws InterruptedException, ExecutionException {
        Future<Multiton> f = multitons.get(key);
        if (f == null) {
            FutureTask<Multiton> ft = new FutureTask<>(creator);
            f = multitons.putIfAbsent(key, ft);
            if (f == null) {
                f = ft;
                ft.run();
            }
        }
        return f.get();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...