JAVA如何判断代码同时被两个线程执行

cto_Lane 发布于 2016/09/16 13:58
阅读 676
收藏 0

在并发环境下,JAVA如何用日志记录同一段代码被两个线程同时执行?能否帮我看一下这段代码有没有问题:

class SeckillThread implements Callable<ApiMessage> {


private GroupProduct product;


private GroupProductOrder order;


private Member member;


private String giftMemberId;


private String logId;


public SeckillThread(GroupProduct product, GroupProductOrder order,
Member member, String giftMemberId, String logId) {
super();
this.product = product;
this.order = order;
this.member = member;
this.giftMemberId = giftMemberId;
this.logId = logId;
}


@Override
public ApiMessage call() throws Exception {
ApiMessage msg = new ApiMessage();


RedisUtil.lock(RedisLockHandler.LOCK_GROUPBUY);


try {


Integer count = order.getCount();

log.info("用户"
+ member.getId()
+ "在["
+ DateUtils.formatDate(new Date(),
"yyyy-MM-dd HH🇲🇲ss:SSS") + "]秒杀开始,订单数量>>>"
+ count);

msg = checkCount(count, product, member);
if (ApiMessage.Type.error.equals(msg.getType())) {
return msg;
}


String sql = "select a.surplusCount from nxh_group_product a where a.id='"
+ product.getId() + "'";


List list = groupProductService.findBySql(sql, null, Map.class);


Map map = (Map) list.get(0);


// 获取商品的剩余数量
Integer surplusCount = (Integer) map.get("surplusCount");
if (surplusCount == 0) {
msg.setType(ApiMessage.Type.error);
msg.setResultMsg("该商品已售完,下次再来吧!");
return msg;
}


log.info("用户"
+ member.getId()
+ "在["
+ DateUtils.formatDate(new Date(),
"yyyy-MM-dd HH🇲🇲ss:SSS") + "]执行秒杀,剩余数量>>>"
+ surplusCount);


if (count > surplusCount) {
msg.setType(ApiMessage.Type.error);
msg.setResultMsg("订单数量不能超过剩余数量,现在还剩余:" + surplusCount
+ "个商品!");
return msg;
}


Shop shop = product.getShop();


order = saveGroupBuyOrder(order, product, member, giftMemberId);


//更新商品的剩余数量
Integer newCuSurPlusCount=surplusCount - count;
//product.setSurplusCount(surplusCount - count);

String updateSuCountSql="update nxh_group_product set surplusCount="+newCuSurPlusCount+" where id='"+product.getId()+"'";

groupProductService.updateBySql(updateSuCountSql, null);


//从数据库中查询真实的剩余数量
List newSucountList = groupProductService.findBySql(sql, null, Map.class);


Map newSMap = (Map) newSucountList.get(0);

Integer newSurplusCount = (Integer) newSMap.get("surplusCount");



if (shop.getInvalidTime() != null) {
Date invalidDate = executeJob(order.getId(), 8,
shop.getInvalidTime());
order.setInvalidDate(invalidDate);
groupProductOrderService.update(order);
}


if (StringUtils.isNotBlank(logId)) {
SeckillLog log = seckillLogService.find(logId);
log.setOrderId(order.getId());
log.setSurplusCount(newCuSurPlusCount);
seckillLogService.update(log);
}


log.info("用户"
+ member.getId()
+ "在["
+ DateUtils.formatDate(new Date(),
"yyyy-MM-dd HH🇲🇲ss:SSS") + "]秒杀结束,剩余数量>>>代码中的剩余数量"+newCuSurPlusCount
+">>>数据库中真实的剩余数量"+ newSurplusCount);


msg.setType(ApiMessage.Type.success);
msg.setResultMsg("提交订单成功!");
msg.setData(order);
} catch (Exception e) {
// TODO Auto-generated catch block
log.info("秒杀异常信息=========="+e.toString());
throw new Exception(e);
} finally {
RedisUtil.unLock(RedisLockHandler.LOCK_GROUPBUY);
}
return msg;
}
}




加载中
0
乌龟壳
乌龟壳
日志内容加上线程id
乌龟壳
乌龟壳
回复 @cto_Lane : 我一般日志模块都自己封装的,是不是线程安全那些自己很清楚,别的产品不清楚哦
c
cto_Lane
已经加上的,现在我们这边有个问题是这样的,在秒杀活动中,在开始秒杀和结束秒杀都做了日志,但有的线程就只打印了结束秒杀的日志,开始秒杀的日志就没有打印,这样的线程秒杀结束后剩余数量就存在问题,我分析可能是这样的线程和其他线程在同一时间执行了开始秒杀的日志代码,但日志只打印出了其中的一个线程的日志,logback会不会出现这样的问题?
0
很成立
很成立
你的代码不是已经加锁了么?怎么会有两个线程同时执行到输出开始秒杀日志的代码的?
0
V
ValSong

问题 没太看明白 不过 可以给你挑挑刺

尽量少用 + 来 拼接字符串 用 StringBuffer

log.info("xxx"+xxxx);这种 也不好

建议用 slf4j代替改成log.info("xxx{}",xxx};这样的


还有看你好多都是查询List然后get(0)如果你是用的hibernate实际上可以使用

Query query = getSession().createQuery(hql);
return query.uniqueResult();这样来返回单一结果

还有// TODO Auto-generated catch block 这种东西最好删掉

返回顶部
顶部