简体   繁体   中英

Using Threads and Flyweight pattern together in Java?

I'm new to both multi-threading and using design patterns.

I've some threads using explicit multi-threading and each is suppose to compute the factorial of a number if it hasn't been computed ever by any thread. I'm using Flyweight Pattern for this.

    private final long Comp;
    private static Map<String, Fact> instances=new HashMap<String, Fact>();

    private Fact(long comp) {
        Comp=comp;
    }

    public static Fact getInstance(int num){
        String key=String.valueOf(num);
        if(!instances.containsKey(key)){
            int comp=//calculate factorial of num
            instances.put(key, new Fact(comp));
        }
        return instances.get(key);
    }

    public long get_Comp(){
        return this.Comp;
    }
}
public class Th implements Runnable {
    // code elited
    @Override
    public void run() {
        //get number and check if it's already in the HashMap, if no, 
          compute
    }

}

If I do so then is it right to say that my Threads Th are computing Factorials?

If I add the computation in Fact (Flyweight) class then does it remain Flyweight, I guess yes.

Any other way of doing what I wish would be highly appreciated as well.

There's a couple of aims you might have here. What to do is dependent on what you are trying to do.

So it seems in this case you are attempting to avoid repeated computation, but that computation is not particularly expensive. You could run into a problem of lock contention. Therefore, to make it thread safe use ThreadLocal<Map<String, Fact>> . Potentially InheritableThreadLocal<Map<String, Fact>> where childValue copies the Map .

Often there are a known set of values that are likely to be common, and you just want these. In that case, compute a Map (or array) during class static initialisation.

If you want the flyweights to be shared between thread and be unique, use ConcurrentHashMap with together with the Map.computeIfAbsent method.

If you want the flyweights to be shared between thread, be unique and you want to make sure you only do the computation once, it gets a bit more difficult. You need to put (if absent) a placeholder into the ConcurrentMap ; if the current thread wins replace that with the computed value and notify, otherwise wait for the computation.

Now if you want the flyweights to be garbage collected, you would want WeakHashMap . This cannot be a ConcurrentMap using the Java SE collections which makes it a bit hopeless. You can use good old fashioned locking. Alternatively the value can be a WeakReference<Fact> , but you'll need to manage eviction yourself.

It may be that a strong reference to Fact is only kept intermittently but you don't want it to be recreated too often, in which case you will need SoftReference instead of WeakReference . Indeed WeakHashMap can behave surprisingly , in some circumstances causing performance to drop to unusable after previously working fine.

(Note, in this case your Map would be better keyed on Integer .)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM