12.23软工踩坑
12.23软工踩坑
这里应该是alterRoomNumber
这段代码也有问题
要加一句
如下:
if (waitqueueThis.getIsWaiting()==1){
//如果在等待中,更新等待时间
Date lastRequestTime = waitqueueThis.getLastRequestTime();
LocalDateTime nowTime = LocalDateTime.now();
LocalDateTime lastRequestTimeLocal = LocalDateTime.ofInstant(lastRequestTime.toInstant(), ZoneId.systemDefault());
Duration duration = Duration.between(lastRequestTimeLocal, nowTime);
long seconds = duration.toSeconds();
waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, room_number)
.set(Waitqueue::getWaitingTime, waitqueueThis.getWaitingTime().add(BigDecimal.valueOf(seconds)))
.set(Waitqueue::getLastRequestTime,new Date())
.update();
}
我们看下面这段代码,里面藏着一个很隐蔽的问题
@Override
public StatusRsp getAirconditioner(Long room_number) {
int totalUsingNum = 0;
Airconditioner airconditioner = this.lambdaQuery().eq(Airconditioner::getId, room_number).one();
Room room = roomService.lambdaQuery().eq(Room::getRoomNumber, room_number).one();
Waitqueue waitqueueThis = waitqueueService.lambdaQuery().eq(Waitqueue::getRoomNum, room_number).one();
if (waitqueueThis.getIsWaiting() == 1) {
//如果在等待中,更新等待时间
Date lastRequestTime = waitqueueThis.getLastRequestTime();
LocalDateTime nowTime = LocalDateTime.now();
LocalDateTime lastRequestTimeLocal = LocalDateTime.ofInstant(lastRequestTime.toInstant(), ZoneId.systemDefault());
Duration duration = Duration.between(lastRequestTimeLocal, nowTime);
long seconds = duration.toSeconds();
waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, room_number)
.set(Waitqueue::getWaitingTime, waitqueueThis.getWaitingTime().add(BigDecimal.valueOf(seconds)))
.set(Waitqueue::getLastRequestTime, new Date())
.update();
}
List<Airconditioner> airconditionerList = this.lambdaQuery().list();
int rate = airconditioner.getSpeed();
//如果使用空调数小于3,则可以将等待队列中的空调启动
for (Airconditioner airconditioner1 : airconditionerList) {
if (airconditioner1.getPower() == 1) {
totalUsingNum++;
}
}
List<Waitqueue> list = waitqueueService.lambdaQuery().eq(Waitqueue::getIsWaiting, 1)
.orderBy(true, false, Waitqueue::getLastRequestTime)
.list();
List<Airconditioner> usingACList = this.lambdaQuery()
.eq(Airconditioner::getPower, 1)
.orderBy(true, false, Airconditioner::getAcUsageTime)
.list();
String alterRoomNumber = null;
if (usingACList.size() > 0) {
Airconditioner alterAC = usingACList.get(0);
alterRoomNumber = alterAC.getRoomId();
}
int size = list.size();//等待中的空调数量
if (totalUsingNum < 3 && size > 0) {
int canUseNum = 3 - totalUsingNum;
log.info("等待队列中的空调(按照上次调用时间降序):{}", list);
for (int i = 0; i < Math.min(canUseNum, size); i++) {
int num = list.get(i).getRoomNum();
//将等待时间超过20s的空调开启,并且移出等待队列
this.lambdaUpdate().eq(Airconditioner::getId, num)
.set(Airconditioner::getPower, 1)
.update();
waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, num)
.set(Waitqueue::getIsWaiting, 0)
.set(Waitqueue::getWaitingTime, BigDecimal.valueOf(0))
.update();
}
}
//如果超过三个空调在使用中,需要一个调度算法,找到等待时间超过20s的空调,换掉总使用时间最长的空调
if (totalUsingNum == 3 && size > 0) {
for (Waitqueue waitRoom : list) {
if (waitRoom.getWaitingTime().compareTo(BigDecimal.valueOf(20)) > 0) {
//找到等待时间超过20s的空调,开启
int num = waitRoom.getRoomNum();
this.lambdaUpdate().eq(Airconditioner::getId, num)
.set(Airconditioner::getPower, 1)
.set(Airconditioner::getQueue,0)
.update();
waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, num)
.set(Waitqueue::getIsWaiting, 0)
.set(Waitqueue::getWaitingTime, BigDecimal.valueOf(0))
.set(Waitqueue::getLastRequestTime,new Date())
.set(Waitqueue::getWaitingTime,0)
.update();
//将使用时间最长的空调,关闭
this.lambdaUpdate().eq(Airconditioner::getId, alterRoomNumber)
.set(Airconditioner::getPower, 0)
.set(Airconditioner::getQueue,1)
.update();
waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, alterRoomNumber)
.set(Waitqueue::getIsWaiting, 1)
.set(Waitqueue::getWaitingTime, BigDecimal.valueOf(0))
.set(Waitqueue::getLastRequestTime,new Date())
.set(Waitqueue::getWaitingTime,0)
.update();
}
}
}
List<Waitqueue> waitqueueList = waitqueueService.lambdaQuery().list();
if (airconditioner == null) {
return null;
}
if (airconditioner.getPower() == 1) {
//空调在使用过程中,实时计算费用
LocalDateTime nowTime = LocalDateTime.now();
Date lastStartTime = airconditioner.getLastStartTime();
LocalDateTime lastAcUseTime = LocalDateTime.ofInstant(lastStartTime.toInstant(), ZoneId.systemDefault());
Duration duration = Duration.between(lastAcUseTime, nowTime);
//计算空调距离数据库中的lastUseTime到现在的时间差
long seconds = duration.toSeconds();
//log.info("距离上次使用的秒数:{}", seconds);
BigDecimal fee = BigDecimal.valueOf(1.0 * seconds * airconditioner.getSpeed() / 3 / 60);
//room更新费用
room.setAcFee(room.getAcFee().add(fee));
room.setAcUsageTime(room.getAcUsageTime().add(BigDecimal.valueOf(1.0 * seconds / 3 / 60)));
room.setTotalFee(room.getTotalFee().add(fee));
if (room.getCurrentTemperature().compareTo(airconditioner.getTemperature()) < 0) {
//房间温度小于设定温度
room.setCurrentTemperature(room.getCurrentTemperature().add(BigDecimal.valueOf(1.0 * seconds / 60)));
} else {
//房间温度大于设定温度
BigDecimal subtract = room.getCurrentTemperature().subtract(BigDecimal.valueOf(1.0 * seconds / 60));
room.setCurrentTemperature(room.getCurrentTemperature().subtract(BigDecimal.valueOf(1.0 * seconds / 60)));
}
roomService.lambdaUpdate().eq(Room::getRoomNumber, room_number).update(room);
//airconditioner更新使用时间
airconditioner.setLastStartTime(new Date());
this.lambdaUpdate().eq(Airconditioner::getId, room_number).update(airconditioner);
} else {
//空调未使用,更新房间温度
if (room.getCurrentTemperature().compareTo(BigDecimal.valueOf(room.getEnvironmentTemperature())) < 0) {
//房间温度小于环境温度
roomService.lambdaUpdate().eq(Room::getRoomNumber, room_number)
.set(Room::getCurrentTemperature,
room.getCurrentTemperature().add(BigDecimal.valueOf(RateEnums.getEnumByValue(rate).getText() / 60)));
} else {
//房间温度大于环境温度
roomService.lambdaUpdate().eq(Room::getRoomNumber, room_number)
.set(Room::getCurrentTemperature,
room.getCurrentTemperature().subtract(BigDecimal.valueOf((RateEnums.getEnumByValue(rate).getText() / 60))));
}
}
StatusRsp result = new StatusRsp();
result.setMode(airconditioner.getMode());
result.setSpeed(SpeedEnums.getEnumByValue(airconditioner.getSpeed()).getText());
result.setPower((airconditioner.getPower() == 1));
result.setCost(room.getAcFee());
//queue里面
result.setQueue(String.valueOf(waitqueueThis.getIsWaiting()));
result.setTime(room.getAcUsageTime());
return result;
}
}
问题就出在115行的代码
this.lambdaUpdate().eq(Airconditioner::getId, room_number).update(airconditioner);
本意是想计算出空调使用的时间然后计算费用加到总计费上面,但是用了update(airconditioner),这就出大问题了,因为airconditioner我们是从数据库中查出来的,但是呢,在上面的语句中我们有一个调度的逻辑,也就是说我们可能已经把数据库中空调的开关状态改变了,但是这里又把它还原了!