关于容器是单例,容器一定需要使用线程安全的集合吗

Pack 发布于 2020-02-28 17:52
阅读 279
收藏 0
分类:设计模式
  1. 使用的容器集合 在getBean 加锁后,还有必要使用线程安全的集合吗?
  2. 如果不使用会造成什么样的后果?


public class DependencyInjectionSingleton {

// 在 getBean 加锁后 这个地方有必要使用 ConcurrentHashMap 吗 private static final Map<String, Object> IOC = new HashMap<>();

private DependencyInjectionSingleton() { System.out.println("我实例化了"); }

// 方法这儿必须加锁,不然会实例多个 public static Object getBean(String name) { synchronized (IOC) { if (!IOC.containsKey(name)) { try { Object obj = Class.forName(name).newInstance(); IOC.put(name, obj); return obj; } catch (Exception e) { e.printStackTrace(); } } return IOC.get(name); } }

static class TestRun implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "---" + getBean("create.singleton.inject.DependencyInjectionSingleton")); } }

public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); ThreadPoolExecutor executor = ThreadPool.getExecutor(); executor.execute(new TestRun()); executor.execute(new TestRun()); executor.execute(new TestRun()); executor.execute(new TestRun()); executor.execute(new TestRun()); executor.execute(new TestRun()); executor.shutdown(); Thread thread = new Thread(new TestRun()); thread.start(); thread.join(); long end = System.currentTimeMillis(); System.out.println("耗时--" + (end - start) + "ms"); }

}

多次运行结果 不使用 ConcurrentHashMap 没有发现异常情况。

483
Pack
Pack

第一:HashMap自身是非线程安全的集合类。
第二:Synchronized的原则尽量只锁住最小范围,你这种锁法会导致getBean的效率严重下降,没有高并发可言,这单例模式本身是为了应对维护大量的单例Bean存在的,结果在进方法就锁了,跟在方法签名直接写Synchronized没区别。
第三:ConcurrentHashMap是1.8提供一个支持高并发的线程安全的集合类。用在该场景下本身就不用关注map是否线程安全,只需要关注if(!IOC.containsKey(name))这里的线程安全就可以了。

这样来说getBean方法才有更高的效率。

请先 登录 后评论