java - 如何在并发环境中只创建一个实例

标签 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。

最佳答案

嗯,最简单的方法就是使您的 ServiceHandle 函数同步。那么一次只能有一个线程在里面,因此,每个 bean 只会创建一个实例。

这可行,但可能会成为瓶颈,当有很多线程请求这些 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);
}

关于java - 如何在并发环境中只创建一个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27872357/

相关文章:

java - 我们如何比较两个键和值不区分大小写的 HashMap

java - YouTube Api v3:列出播放列表视频

java - 创建类似祖玛的网页游戏 - 使用哪种技术?

java - WeakHashMap 与并发修改

java - 并发性 - 为什么这个函数中的最后一条指令永远不会执行?

java - 这段代码是 ORM 的正常行为吗?

go - 具有多个用户的服务器实例

java - Android 2.1 SDK + ConcurrentHashMap$ValueIterator 与 GC

Java并行查找数组的最小值

java - 如何在 OS X 中使用 Java 找到用户的 'Documents' 文件夹?