可学习如下代码
public boolean searchBuyLimit(Long userId , Long goodsId , Integer num , ServiceRequest request){
SearchBuyLimitRequest searchBuyLimitRequest = new SearchBuyLimitRequest(request);
BuyLimitVO buyLimitVO = new BuyLimitVO();
buyLimitVO.setUserId(userId);
buyLimitVO.setGoodsId(goodsId);
buyLimitVO.setNum(num);
searchBuyLimitRequest.setBuyLimit(buyLimitVO);
ServiceResponse response = buyLimitService.searchBuyLimit(searchBuyLimitRequest);
if (response.isSuccess() && response.getData().isAllow()){
return true;
}else{
return false;
}
}
Map接口
Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value;
键(key值)不可重复,value值可以重复,一个value值可以和很多key值形成对应关系,每个键最多只能映射到一个值。
Map支持泛型,形式如:Map
Map中使用put(K key,V value)方法添加
Map中使用Remove(K key)方法删除
HashMap类(初始size为16)
HashMap是Map的一个重要实现类,也是最常用的,基于哈希表实现
HashMap中的Entry对象是无序排列的
Key值和value值都可以为null,但是一个HashMap只能有一个key值为null的映射(key值不可重复)
Hashtable类(初始size为11,增加的方式是 old*2+1)
Hashtable也实现了Map接口,与HashMap基本相似,只有以下不同
他们两个都是无序的
HashMap是非synchronized的,可以接受为null的键值(key)和值(value)
Hashtable是synchronized,Hashtable是线程安全的,多个线程可以共享一个Hashtable,Hashtable不允许null值
如果没有正确的同步的话,多个线程是不能共享HashMap, HashMap不能保证随着时间的推移Map中的元素次序是不变的
因为Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,那么使用HashMap性能比Hashtable好
建议:如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。
@Resource 注解被用来激活一个命名资源(named resource)的依赖注入。通常来说有两种使用方式。
@Resource(name="data") public void setData(Data data) { this.data= data; }
但是直接使用@Resource注解一个域(field)同样是可能的。通过不暴露setter方法,代码愈发紧凑并且还提供了域不可修改的额外益处。该方式被应用到setter方法的时候,默认名是从相应的属性衍生出来,如下代码所示:
@Resource
private DataSource data; // inject the bean named 'data'
学习如下代码
callableList.add(() -> {
ServiceResponse invokeResp = bizInvoke.doServiceInvoke(request);
if (!invokeResp.isSuccess()) {
throw new RollbackException(invokeResp.getDesc());
}
return invokeResp;
});
(此种情况下事务不能处理)
转载自 https://www.cnblogs.com/ZJOE80/p/5671567.html 感觉这篇博客介绍的很详细
库存超卖问题也就是在遇到如团购、秒杀、特价之类的活动时,访问量激增、上千甚至上万人抢购一个商品,如何控制库存不让出现超买防止造成不必要的损失。
解决方案1:
将存库从MySQL前移到Redis中,所有的写操作放到内存中,由于Redis中不存在锁故不会出现互相等待,并且由于Redis的写性能和读性能都远高于MySQL,这就解决了高并发下的性能问题。然后通过队列等异步手段,将变化的数据异步写入到DB中。
优点:解决性能问题
缺点:没有解决超卖问题,同时由于异步写入DB,存在某一时刻DB和Redis中数据不一致的风险。
解决方案2:
引入队列,然后将所有写DB操作在单队列中排队,完全串行处理。当达到库存阀值的时候就不在消费队列,并关闭购买功能。这就解决了超卖问题。
优点:解决超卖问题,略微提升性能。
缺点:性能受限于队列处理机处理性能和DB的写入性能中最短的那个,另外多商品同时抢购的时候需要准备多条队列。
解决方案3:
将写操作前移到Memcached中,同时利用Memcached的轻量级的锁机制CAS来实现减库存操作。
优点:读写在内存中,操作性能快,引入轻量级锁之后可以保证同一时刻只有一个写入成功,解决减库存问题。
缺点:没有实测,基于CAS的特性不知道高并发下是否会出现大量更新失败?不过加锁之后肯定对并发性能会有影响。
解决方案4:
将提交操作变成两段式,先申请后确认。然后利用Redis的原子自增操作(相比较MySQL的自增来说没有空洞),同时利用Redis的事务特性来发号,保证拿到小于等于库存阀值的号的人都可以成功提交订单。然后数据异步更新到DB中。
优点:解决超卖问题,库存读写都在内存中,故同时解决性能问题。
缺点:由于异步写入DB,可能存在数据不一致。另可能存在少买,也就是如果拿到号的人不真正下 订单,可能库存减为0,但是订单数并没有达到库存阀值。
总结方法:
在枚举类型中可以添加构造方法,但是规定构造方法必须为private修饰符所修饰,可学习下面代码
//可以把PopUpType 理解为一个类
public enum PopUpType {
NEWPACK(1, "新客大礼包"),
OLDCOUPON(2, "老客优惠卷"),
EXITCOUPON(3, "未使用的优惠卷"),
ACTIVEPOP(4, "活动弹窗"),;
//而OLDCOUPON就是这个类的一个实例,因此,我们现在有4个这样的实例
public static PopUpType getStatus(int status) {
for (PopUpType type : values()) {
if (status == type.getId()) {
return type;
}
}
return null;
}
private int id;
private String desc;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
PopUpType() {
}
PopUpType(int id, String desc) {
this.id = id;
this.desc = desc;
}
public static PopUpType valueOfCode(int code){
for (PopUpType ts : PopUpType.values()){
if (ts.getId() == code){
return ts;
}
}
return null;
}
}
其适用于Java的序列化机制。而Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。
具体序列化步骤:
其一是默认的1L,比如:private static final long serialVersionUID = 1L;
其二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如我们常见的:
private static final long serialVersionUID = 1214456890L;