新增线程池异步处理程序

hehai
shijie 4 years ago
parent a068d0a086
commit cd5a2fc68c
  1. 5
      pom.xml
  2. 10
      src/main/java/com/msdw/tms/api/EvaluationRecordControllerApi.java
  3. 25
      src/main/java/com/msdw/tms/config/MyThreadConfig.java
  4. 14
      src/main/java/com/msdw/tms/config/ThreadPoolConfigProperties.java
  5. 9
      src/main/java/com/msdw/tms/controller/EvaluationRecordController.java
  6. 8
      src/main/java/com/msdw/tms/service/EvaluationRecordService.java
  7. 182
      src/main/java/com/msdw/tms/service/impl/EvaluationRecordServiceImpl.java
  8. 5
      src/main/resources/application.yml

@ -145,6 +145,11 @@
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>

@ -4,6 +4,8 @@ import com.msdw.tms.common.utils.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.concurrent.ExecutionException;
/**
* 记录用户测评信息
@ -42,13 +44,13 @@ public interface EvaluationRecordControllerApi {
* 上一题
*/
@ApiOperation(value = "上一题", notes = "上一题")
R previousQuestion(Integer evaluationRecordId, Integer currentQuestionSortNo, String userAnswer);
R previousQuestion(Integer evaluationRecordId, Integer currentQuestionSortNo, String userAnswer) throws ExecutionException, InterruptedException;
/**
* 下一题
*/
@ApiOperation(value = "下一题", notes = "下一题")
R nextQuestion(Integer evaluationRecordId, Integer currentQuestionSortNo, String userAnswer);
R nextQuestion(Integer evaluationRecordId, Integer currentQuestionSortNo, String userAnswer) throws ExecutionException, InterruptedException;
/**
* 提交之前查询是否还有未做完的试题
@ -60,13 +62,13 @@ public interface EvaluationRecordControllerApi {
* 提交测评
*/
@ApiOperation(value = "提交测评", notes = "提交测评")
R submitEvaluation(Integer evaluationRecordId, Integer currentQuestionSortNo, String userAnswer, Integer userId);
R submitEvaluation(Integer evaluationRecordId, Integer currentQuestionSortNo, String userAnswer, Integer userId) throws ExecutionException, InterruptedException;
/**
* 成绩详情
*/
@ApiOperation(value = "成绩详情", notes = "成绩详情")
R evaluationScoreDetail(Integer evaluationRecordId);
R evaluationScoreDetail(Integer evaluationRecordId) throws ExecutionException, InterruptedException;
/**
* 查询是否能够开启实验

@ -0,0 +1,25 @@
package com.msdw.tms.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
//@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
return new ThreadPoolExecutor(pool.getCoreSize(),
pool.getMaxSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
}

@ -0,0 +1,14 @@
package com.msdw.tms.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "tms.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}

@ -10,6 +10,7 @@ import com.msdw.tms.service.QuestionsService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;
/**
@ -60,7 +61,7 @@ public class EvaluationRecordController implements EvaluationRecordControllerApi
@PostMapping("/previous")
public R previousQuestion(@RequestParam("evaluationRecordId") Integer evaluationRecordId,
@RequestParam("currentQuestionSortNo") Integer currentQuestionSortNo,
@RequestParam(value = "userAnswer", required = false) String userAnswer) {
@RequestParam(value = "userAnswer", required = false) String userAnswer) throws ExecutionException, InterruptedException {
EvaluationRecordVO evaluationRecordVO = evaluationRecordService.convertQuestion(evaluationRecordId, currentQuestionSortNo, userAnswer, currentQuestionSortNo - 1);
return R.ok().put("data", evaluationRecordVO);
}
@ -69,7 +70,7 @@ public class EvaluationRecordController implements EvaluationRecordControllerApi
@PostMapping("/next")
public R nextQuestion(@RequestParam("evaluationRecordId") Integer evaluationRecordId,
@RequestParam("currentQuestionSortNo") Integer currentQuestionSortNo,
@RequestParam(value = "userAnswer", required = false) String userAnswer) {
@RequestParam(value = "userAnswer", required = false) String userAnswer) throws ExecutionException, InterruptedException {
EvaluationRecordVO evaluationRecordVO = evaluationRecordService.convertQuestion(evaluationRecordId, currentQuestionSortNo, userAnswer, currentQuestionSortNo + 1);
return R.ok().put("data", evaluationRecordVO);
}
@ -86,14 +87,14 @@ public class EvaluationRecordController implements EvaluationRecordControllerApi
public R submitEvaluation(@RequestParam("evaluationRecordId") Integer evaluationRecordId,
@RequestParam("currentQuestionSortNo") Integer currentQuestionSortNo,
@RequestParam(value = "userAnswer", required = false) String userAnswer,
@RequestParam("userId") Integer userId) {
@RequestParam("userId") Integer userId) throws ExecutionException, InterruptedException {
EvaluationRecordSubmitVO recordSubmitVO = evaluationRecordService.submitEvaluation(evaluationRecordId, currentQuestionSortNo, userAnswer, userId);
return R.ok().put("data", recordSubmitVO);
}
@Override
@GetMapping("/detail")
public R evaluationScoreDetail(Integer evaluationRecordId) {
public R evaluationScoreDetail(Integer evaluationRecordId) throws ExecutionException, InterruptedException {
EvaluationRecordDetailVO detailVO = evaluationRecordService.evaluationDetail(evaluationRecordId);
return R.ok().put("data", detailVO);
}

@ -6,6 +6,8 @@ import com.msdw.tms.entity.vo.EvaluationRecordDetailVO;
import com.msdw.tms.entity.vo.EvaluationRecordSubmitVO;
import com.msdw.tms.entity.vo.EvaluationRecordVO;
import java.util.concurrent.ExecutionException;
/**
* 记录用户测评信息
*
@ -20,14 +22,14 @@ public interface EvaluationRecordService extends IService<EvaluationRecordEntity
EvaluationRecordVO convertQuestion(Integer evaluationRecordId,
Integer currentQuestionSortNo,
String userAnswer,
Integer changeSortNo);
Integer changeSortNo) throws ExecutionException, InterruptedException;
EvaluationRecordSubmitVO submitEvaluation(Integer evaluationRecordId,
Integer currentQuestionSortNo,
String userAnswer,
Integer userId);
Integer userId) throws ExecutionException, InterruptedException;
EvaluationRecordDetailVO evaluationDetail(Integer evaluationRecordId);
EvaluationRecordDetailVO evaluationDetail(Integer evaluationRecordId) throws ExecutionException, InterruptedException;
String selectNotMade(Integer evaluationRecordId);

@ -25,6 +25,9 @@ import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;
@ -43,6 +46,9 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
@Autowired
StringRedisTemplate redisTemplate;
@Autowired
ThreadPoolExecutor executor;
private String REMAINING_TINE_KEY = "REMAINING_TINE";
@Override
@ -51,7 +57,7 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
//TODO 接口幂等性处理
//根据用户id和是否提交,查询测评记录信息
EvaluationRecordEntity one = this.getOne(new QueryWrapper<EvaluationRecordEntity>().eq("user_id", userId)
.eq("evaluation_status", Constant.Submit.SUBMIT.getType()));
.eq("evaluation_status", Constant.Submit.NOT_SUBMIT.getType()));
if (one == null) {
//随机抽取试题数据
@ -70,8 +76,6 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
EvaluationQuestionEntity evaluationQuestionEntity = new EvaluationQuestionEntity();
evaluationQuestionEntity.setEvaluationRecordId(evaluationRecord.getId());
evaluationQuestionEntity.setQuestionId(question);
// evaluationQuestionEntity.setIsTure(Constant.QuestionIsTure.FALSE.getType());
// evaluationQuestionEntity.setQuestionStatus(Constant.QuestionStatus.NOT_MADE.getType());
return evaluationQuestionEntity;
}).collect(Collectors.toList());
@ -139,29 +143,33 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
}
@Override
@Transactional
public EvaluationRecordVO convertQuestion(Integer evaluationRecordId,
Integer currentQuestionSortNo,
String userAnswer,
Integer changeSortNo) {
Integer changeSortNo) throws ExecutionException, InterruptedException {
if (currentQuestionSortNo < 1
|| currentQuestionSortNo > this.getById(evaluationRecordId).getTotalQuestionNum()
|| changeSortNo < 1
|| changeSortNo > this.getById(evaluationRecordId).getTotalQuestionNum()) {
ExceptionCast.cast(CommonCode.INVALID_PARAM);
}
//TODO 异步调用。。。
//提交当前试题信息
boolean result = submitCurrentQuestion(evaluationRecordId,
currentQuestionSortNo,
userAnswer,
changeSortNo);
if (!result) {
ExceptionCast.cast(CommonCode.FAIL);
}
CompletableFuture<Void> submitCurrentQuestionFuture = CompletableFuture.runAsync(()
-> submitCurrentQuestion(evaluationRecordId, currentQuestionSortNo, userAnswer), executor);
//修改测评记录表当前题目顺序号
CompletableFuture<Void> updateCurrentSortNoFuture = CompletableFuture.runAsync(()
-> updateCurrentSortNo(changeSortNo, evaluationRecordId), executor);
CompletableFuture<EvaluationRecordVO> future = CompletableFuture.supplyAsync(()
-> this.getBaseMapper().selectVOByInfo(evaluationRecordId, changeSortNo), executor);
CompletableFuture.allOf(submitCurrentQuestionFuture, updateCurrentSortNoFuture, future).get();
EvaluationRecordVO evaluationRecordVO = future.get();
//查询下一题信息
EvaluationRecordVO evaluationRecordVO = this.getBaseMapper().selectVOByInfo(evaluationRecordId, changeSortNo);
evaluationRecordVO.setQuestionTypeName(getQuestionTypeName(evaluationRecordVO.getQuestionType()));
return evaluationRecordVO;
}
@ -170,67 +178,81 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
public EvaluationRecordSubmitVO submitEvaluation(Integer evaluationRecordId,
Integer currentQuestionSortNo,
String userAnswer,
Integer userId) {
Integer userId) throws ExecutionException, InterruptedException {
//清除redis中的倒计时
String key = REMAINING_TINE_KEY + userId;
redisTemplate.delete(key);
boolean result = submitCurrentQuestion(evaluationRecordId,
currentQuestionSortNo,
userAnswer,
null);
if (!result) {
ExceptionCast.cast(CommonCode.FAIL);
}
CompletableFuture<Void> deleteKeyFuture = CompletableFuture.runAsync(() -> {
String key = REMAINING_TINE_KEY + userId;
redisTemplate.delete(key);
}, executor);
CompletableFuture<Void> submitCurrentQuestionFuture = CompletableFuture.runAsync(()
-> submitCurrentQuestion(evaluationRecordId, currentQuestionSortNo, userAnswer), executor);
//修改提交时间和测评记录状态
CompletableFuture<Void> updateEvaluationFuture = CompletableFuture.runAsync(() -> {
EvaluationRecordEntity entity = new EvaluationRecordEntity();
entity.setId(evaluationRecordId);
entity.setEvaluationStatus(Constant.Submit.SUBMIT.getType());
entity.setSubmitTime(new Date());
this.updateById(entity);
}, executor);
//TODO 优化,使用多线程异步调用
//修改提交时间
EvaluationRecordEntity entity = new EvaluationRecordEntity();
entity.setId(evaluationRecordId);
entity.setEvaluationStatus(Constant.Submit.SUBMIT.getType());
entity.setSubmitTime(new Date());
this.updateById(entity);
EvaluationRecordSubmitVO submitVO = new EvaluationRecordSubmitVO();
//查询总成绩
int sumScore = evaluationQuestionDao.sumScore(evaluationRecordId);
QueryWrapper<EvaluationQuestionEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("evaluation_record_id", evaluationRecordId)
.eq("is_ture", Constant.QuestionIsTure.TRUE.getType());
//查询答对几题
int count = evaluationQuestionService.count(queryWrapper);
EvaluationRecordEntity evaluationRecord = this.getById(evaluationRecordId);
EvaluationRecordSubmitVO submitVO = new EvaluationRecordSubmitVO();
BeanUtils.copyProperties(evaluationRecord, submitVO);
//正确率
// 创建一个数值格式化对象
NumberFormat numberFormat = NumberFormat.getInstance();
// 设置精确到小数点后2位
numberFormat.setMaximumFractionDigits(2);
submitVO.setCorrectRate(numberFormat.format((float) count / (float) evaluationRecord.getTotalQuestionNum() * 100) + "%");
//是否通过
submitVO.setIsPassed(sumScore > Constant.PASSING_SCORE ? Constant.EVALUATIONN_PASSED : Constant.EVALUATIONN_NOT_PASSED);
//得分
submitVO.setTotalScore(sumScore);
//答对几道
submitVO.setCorrectQuestionNum(count);
CompletableFuture<Void> sumScoreFuture = CompletableFuture.runAsync(() -> {
int sumScore = evaluationQuestionDao.sumScore(evaluationRecordId);
//得分
submitVO.setTotalScore(sumScore);
//是否通过
submitVO.setIsPassed(sumScore > Constant.PASSING_SCORE ? Constant.EVALUATIONN_PASSED : Constant.EVALUATIONN_NOT_PASSED);
}, executor);
CompletableFuture<EvaluationRecordEntity> getByIdFuture = CompletableFuture.supplyAsync(() -> {
EvaluationRecordEntity evaluationRecord = this.getById(evaluationRecordId);
BeanUtils.copyProperties(evaluationRecord, submitVO);
return evaluationRecord;
}, executor);
CompletableFuture<Void> countFuture = getByIdFuture.thenAcceptAsync((res) -> {
QueryWrapper<EvaluationQuestionEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("evaluation_record_id", evaluationRecordId)
.eq("is_ture", Constant.QuestionIsTure.TRUE.getType());
//查询答对几题
int count = evaluationQuestionService.count(queryWrapper);
//答对几道
submitVO.setCorrectQuestionNum(count);
//正确率
// 创建一个数值格式化对象
NumberFormat numberFormat = NumberFormat.getInstance();
// 设置精确到小数点后2位
numberFormat.setMaximumFractionDigits(2);
submitVO.setCorrectRate(numberFormat.format((float) count / (float) res.getTotalQuestionNum() * 100) + "%");
}, executor);
CompletableFuture.allOf(deleteKeyFuture, submitCurrentQuestionFuture, updateEvaluationFuture,
sumScoreFuture, getByIdFuture, countFuture).get();
return submitVO;
}
@Override
public EvaluationRecordDetailVO evaluationDetail(Integer evaluationRecordId) {
//TODO 异步查询
//查询总成绩
int sumScore = evaluationQuestionDao.sumScore(evaluationRecordId);
List<EvaluationDetailVO> evaluationDetailVOS = evaluationQuestionDao.selectDetailByInfo(evaluationRecordId);
public EvaluationRecordDetailVO evaluationDetail(Integer evaluationRecordId) throws ExecutionException, InterruptedException {
EvaluationRecordDetailVO evaluationRecordDetailVO = new EvaluationRecordDetailVO();
evaluationRecordDetailVO.setTotalScore(sumScore);
evaluationRecordDetailVO.setEvaluationDetailVOS(evaluationDetailVOS);
CompletableFuture<Void> sumScoreFuture = CompletableFuture.runAsync(() -> {
//查询总成绩
int sumScore = evaluationQuestionDao.sumScore(evaluationRecordId);
evaluationRecordDetailVO.setTotalScore(sumScore);
}, executor);
CompletableFuture<Void> evaluationDetailVOSFuture = CompletableFuture.runAsync(() -> {
List<EvaluationDetailVO> evaluationDetailVOS = evaluationQuestionDao.selectDetailByInfo(evaluationRecordId);
evaluationRecordDetailVO.setEvaluationDetailVOS(evaluationDetailVOS);
}, executor);
CompletableFuture.allOf(sumScoreFuture, evaluationDetailVOSFuture).get();
return evaluationRecordDetailVO;
}
@ -242,7 +264,7 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
.eq("question_status", Constant.QuestionStatus.NOT_MADE.getType());
List<EvaluationQuestionEntity> list = evaluationQuestionService.list(queryWrapper);
List<Integer> collect = list.stream().map(item -> item.getQuestionSortNo()).collect(Collectors.toList());
List<Integer> collect = list.stream().map(EvaluationQuestionEntity::getQuestionSortNo).collect(Collectors.toList());
if (collect.size() == 0) {
return "已完成全部题目";
}
@ -284,11 +306,9 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
// }
//提交当前试题,并修改当前测评记录表
@Transactional
public boolean submitCurrentQuestion(Integer evaluationRecordId,
Integer currentQuestionSortNo,
String userAnswer,
Integer changeSortNo) {
private void submitCurrentQuestion(Integer evaluationRecordId,
Integer currentQuestionSortNo,
String userAnswer) {
//1、根据当前传递的evaluationRecordId和currentQuestionSortNo查询当前试题
EvaluationQuestionVO evaluationQuestionVO = evaluationQuestionDao.selectByInfo(evaluationRecordId, currentQuestionSortNo);
if (evaluationQuestionVO == null) {
@ -320,19 +340,15 @@ public class EvaluationRecordServiceImpl extends ServiceImpl<EvaluationRecordDao
evaluationQuestion.setQuestionScore(questionPoints);
}
}
int updateQuestion = evaluationQuestionDao.updateById(evaluationQuestion);
//修改测评记录表
if (changeSortNo != null) {
EvaluationRecordEntity evaluationRecordEntity = new EvaluationRecordEntity();
evaluationRecordEntity.setCurrentQuestionSortNo(changeSortNo);
evaluationRecordEntity.setId(evaluationRecordId);
boolean updateRecord = this.updateById(evaluationRecordEntity);
return updateQuestion > 0 && updateRecord;
}
evaluationQuestionDao.updateById(evaluationQuestion);
return updateQuestion > 0;
}
private void updateCurrentSortNo(Integer changeSortNo, Integer evaluationRecordId) {
//修改测评记录表
EvaluationRecordEntity evaluationRecordEntity = new EvaluationRecordEntity();
evaluationRecordEntity.setCurrentQuestionSortNo(changeSortNo);
evaluationRecordEntity.setId(evaluationRecordId);
this.updateById(evaluationRecordEntity);
}
}

@ -23,3 +23,8 @@ mybatis-plus:
server:
port: 7000
tms:
thread:
core-size: 20
max-size: 200
keep-alive-time: 10

Loading…
Cancel
Save