在Java中同时使用线程和Flyweight模式?

在Java中同时使用线程和Flyweight模式?,java,multithreading,flyweight-pattern,Java,Multithreading,Flyweight Pattern,我对多线程和使用设计模式都是新手 我有一些线程使用显式多线程,假设每个线程都计算一个数字的阶乘,如果它从来没有被任何线程计算过。我用的是Flyweight图案 private final long Comp; private static Map<String, Fact> instances=new HashMap<String, Fact>(); private Fact(long comp) { Comp=comp;

我对多线程和使用设计模式都是新手

我有一些线程使用显式多线程,假设每个线程都计算一个数字的阶乘,如果它从来没有被任何线程计算过。我用的是Flyweight图案

    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;
    }
}
如果我这样做了,那么说我的线程是计算阶乘是对的吗

如果我添加了计算事实(Flyweight)类,那么它是否仍然是Flyweight,我想是的


我也非常感谢任何其他我希望的方法。

这里有几个目标。做什么取决于你想做什么

因此,在这种情况下,您似乎试图避免重复计算,但这种计算并不特别昂贵。您可能会遇到锁争用问题。因此,要使其线程安全,请使用
ThreadLocal
。可能
InheritableThreadLocal
其中
childValue
复制
Map

通常,有一组已知的值可能很常见,而您只需要这些值。在这种情况下,在类静态初始化期间计算
映射(或数组)

如果希望flyweights在线程之间共享且唯一,请使用
ConcurrentHashMap
Map.computeIfAbsent
方法

如果希望flyweights在线程之间共享,请保持唯一性,并确保只执行一次计算,这会变得有点困难。您需要在
ConcurrentMap
中放置(如果没有)占位符;如果当前线程获胜,则将其替换为计算值并通知,否则等待计算

现在,如果希望对飞锤进行垃圾收集,则需要
WeakHashMap
。这不能是使用JavaSE集合的
ConcurrentMap
,这让它有点绝望。你可以用老式的锁。或者,该值可以是
WeakReference
,但您需要自己管理逐出

可能是对
事实的强引用只是间歇性地保留,但您不希望太频繁地重新创建,在这种情况下,您将需要
软引用
,而不是
软引用
。事实上,
WeakHashMap
可以表现出出乎意料的,在某些情况下会导致性能在之前正常工作后下降到无法使用的


(注意,在这种情况下,
映射
最好键入
整数

哈希映射
不是线程安全的。对于来自多个线程的访问,请考虑<代码> CONCURNESHASMAP 。然后还可以使用
computeIfAbsent
功能。为什么要把钥匙变成
字符串
?您也可以使用
Integer
。对于
long
来说,阶乘也会很快变得太大。谢谢@Thilo,我会记住这一点
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
    }

}