網(wǎng)站開發(fā)工程師面試問哪些問題網(wǎng)絡(luò)營銷推廣渠道
寫享元模式的時候,會想使用ConcurrentHashMap來保證并發(fā),沒有使用雙重鎖會不會有問題?但是在synchronize代碼塊里面需要盡量避免throw異常,希望有經(jīng)驗的同學(xué)能夠給出解答?
1月6號補充:沒有使用雙重鎖會有問題
享元模式UML圖如下:
@Component
public class PayContextFactory extends AbstractPayContextFactory<PayContext> {//享元模式private static final Map<String, PayContext> payContexts = new ConcurrentHashMap<>();@Overridepublic PayContext getContext(Integer payType) {StrategyEnum strategyEnum =payType == 1 ? StrategyEnum.alipay :payType == 2 ? StrategyEnum.wechat :null;if (Objects.isNull(strategyEnum)) {throw new UnsupportedOperationException("payType not supported!");}//嘗試從map中獲取ContextPayContext context = payContexts.get(strategyEnum.name());//第一次調(diào)用if (Objects.isNull(context)) {try {//通過反射,創(chuàng)建具體類PayStrategyInterface payStrategy = (PayStrategyInterface) Class.forName(strategyEnum.getValue()).newInstance();//將具體策略類作為入?yún)?創(chuàng)建payContextPayContext payContext = new PayContext(payStrategy);payContexts.put(strategyEnum.name(), payContext);} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {throw new UnsupportedOperationException("get strategy failed!");}}return payContexts.get(strategyEnum.name());}
}
使用雙重檢查鎖后的代碼
@Component
public class PayContextFactory extends AbstractPayContextFactory<PayContext> {//享元模式private static final Map<String, PayContext> payContexts = new ConcurrentHashMap<>();@Overridepublic PayContext getContext(Integer payType) {StrategyEnum strategyEnum =payType == 1 ? StrategyEnum.alipay :payType == 2 ? StrategyEnum.wechat :null;if (Objects.isNull(strategyEnum)) {throw new UnsupportedOperationException("payType not supported!");}//嘗試從map中獲取ContextPayContext context = payContexts.get(strategyEnum.name());//第一次調(diào)用if (Objects.isNull(context)) {synchronized (payContexts) {context = payContexts.get(strategyEnum.name());if (Objects.isNull(context)) {try {//通過反射,創(chuàng)建具體類PayStrategyInterface payStrategy = (PayStrategyInterface) Class.forName(strategyEnum.getValue()).newInstance();//將具體策略類作為入?yún)?創(chuàng)建payContextPayContext payContext = new PayContext(payStrategy);payContexts.put(strategyEnum.name(), payContext);} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {throw new UnsupportedOperationException("get strategy failed!");}}}}return payContexts.get(strategyEnum.name());}
}