如何在并发环境中仅创建一个实例

时间:2015-01-10 02:47:05

标签: java concurrency

以下是代码:

HashMap<String, Bean> cachedBean;  
public Bean init(String name) {
     return new Bean(name);
}  

void ServiceHandle(String name) {
    if(cachedBean.get(name) == null) {
         Bean newBean = init(name);
         cachedBean.putIfAbsent(newBean);
    }
}

如果1000个客户端使用相同的名称调用ServiceHandle,则将创建1000个bean对象,并且只有其中一个将放入caced地图。有没有办法确保无论同时调用ServiceHandle多少次,都只会创建一个bean。

1 个答案:

答案 0 :(得分:2)

嗯,最简单的方法就是制作ServiceHandle函数synchronized。那么一次只能有一个线程在内部,因此,每个bean只能创建一个实例。

这很有效,但是当有很多线程要求这些bean时,它们可能成为一个瓶颈:他们最终都会在这个函数的入口处等待对方。

这是避免这种情况的一种方法。它可能看起来有点问题,但我喜欢它的是最常见的路径,在所有内容初始化之后根本不需要任何同步或锁定,并且当初始化bean时,只有线程,要求特定的bean被迫等待,而其他人则不受影响:

class BeanHolder {
    // Does not need to be volatile as long as once a bean is initialized it never changes again!
    private Bean bean = null; 
    public Bean getBean(String name) {
       if(bean == null) synchronized(this) {
           if(bean == null) bean = init(name);               
       }
       return bean;
    }      
}

ConcurrentHashMap<String, BeanHolder> beans = new ConcurrentHashMap<>();
Bean serviceHandle(String name)  {
   beans.putIfAbset(name, new BeanHolder());
   return beans.get(name).getBean(name);
}