参考链接: https://blog.csdn.net/le_17_4_6/article/details/118699111
代码案例
多线程工具类 提高执行线程和获取返回数据方法
/** * 多线程工具类 */ public class ConcurrentUtil { /** * 执行任务 * * @param <ResponseModel> 返回的结果集Future ResponseModel * @param executorService ExecutorService * @param callable 回调 * @return Future ResponseModel */ public static <ResponseModel> Future<ResponseModel> doJob(ExecutorService executorService, MyCallable callable) { return (Future<ResponseModel>) executorService.submit(callable); } /** * 获取结果集,执行时会阻塞直到有结果,中间的异常不会被静默 * * @param future Future * @param <ResponseModel> 返回的结果集 ResponseModel * @return ResponseModel */ public static <ResponseModel> ResponseModel futureGet(Future<ResponseModel> future) { try { return future.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } }
公共类
/** * 响应结果类 */ @Data @ToString public class ResponseModel implements Serializable { //消息 private String message; //状态码 private int messageCode; //结果 private Object result; public ResponseModel(String message, int messageCode, Object result) { this.message = message; this.messageCode = messageCode; this.result = result; } public ResponseModel() { } }
public final class StFlag { public StFlag() { } /** * 性别:0-男,1-女 */ public static final String SEX_FLAG_0 = "0"; public static final String SEX_FLAG_1 = "1"; /** * 学生服务 */ public static final String STUDENT_SERVICE = "STUDENT"; /** * 问卷服务 */ public static final String QUESTION_SERVICE = "QUESTION"; }
/** * 多线程业务类 */ @Slf4j @Setter public class MyCallable implements Serializable, Callable<ResponseModel> { //服务名 private String whichServiceName; private StudentController studentController; private RequestStudentModel studentEntity; public MyCallable(String whichServiceName, StudentController studentController, RequestStudentModel studentEntity) { this.whichServiceName = whichServiceName; this.studentController = studentController; this.studentEntity = studentEntity; } @Override public ResponseModel call(){ if (StFlag.STUDENT_SERVICE.equalsIgnoreCase(whichServiceName)){ return studentController.getStudentList(studentEntity); } return studentController.getStudentList(studentEntity); } }
/** * 学生相关控制器,真正业务类,具体业务了逻辑自己实现 */ @RestController @RequestMapping("/student") @Slf4j public class StudentController { @Autowired private StudentService studentService; /** * 查询问卷校验项 * @return */ @PostMapping("/getStudentList") public ResponseModel getStudentList(@RequestBody RequestStudentModel studentEntity){ try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return new ResponseModel("查询成功", 200, ""); } }
测试主类
特别注意, ConcurrentUtil.futureGet(responseRqestionFuture);方法要在所有线程执行完之后执行,否则达不到多线程执行的效果,因为future.get()会阻塞,知道拿到返回值
/** * 多线程控制器 */ @RestController @RequestMapping("/concurrent") @Slf4j public class CurrentController { @Autowired private StudentController studentController; /** * 多线程测试 * @return */ @PostMapping("/current") public ResponseModel getStudentList(@RequestBody RequestStudentModel studentEntity) throws ExecutionException, InterruptedException { log.info("current ---- start "); List list = new ArrayList(); ExecutorService executorService = new ThreadPoolExecutor(2, 2, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(30), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy()); // 另一种方式创建线程池,不推荐,因为不能修改内部参数,比如队列类型 // ExecutorService executorService = Executors.newFixedThreadPool(20); // 多线程调用方式 // MyCallable myCallable= new MyCallable(StFlag.STUDENT_SERVICE,studentController, studentEntity); // Future<ResponseModel> submit = executorService.submit(myCallable); // ResponseModel responseModel1 = submit.get(); long timeStart = System.currentTimeMillis(); // 查询问卷 Future<ResponseModel> responseRqestionFuture = ConcurrentUtil.doJob(executorService, new MyCallable(StFlag.STUDENT_SERVICE,studentController, studentEntity)); // 查询学生 Future<ResponseModel> responseSudentFuture = ConcurrentUtil.doJob(executorService, new MyCallable(StFlag.QUESTION_SERVICE,studentController, studentEntity)); //future.get方法 //线程池线程是异步提交的,但是返回分页结果是需要同步返回,Future的get是个阻塞方法。 // 只有所有的任务全部完成,我们才能用get按照任务的提交顺序依次返回结果, // 调用future.get()方法查看线程池内所有方法是否已执行完成,达到线程异步提交,结果集同步返回的效果。 ResponseModel myCallableResponseModel1 = ConcurrentUtil.futureGet(responseRqestionFuture); ResponseModel myCallableResponseModel2 = ConcurrentUtil.futureGet(responseSudentFuture); long timeMiddle = System.currentTimeMillis(); long longMutiThread = timeMiddle - timeStart; log.info("多线程执行用时为: {}", longMutiThread); list.add("多线程执行用时为: "+longMutiThread); // 单线程查询 ResponseModel responseModel = studentController.getStudentList(studentEntity); ResponseModel studentList = studentController.getStudentList(studentEntity); long timeEnd = System.currentTimeMillis(); long longDingleThread = timeEnd - timeMiddle; log.info("单线程执行用时为: {}", longDingleThread); list.add("单线程执行用时为: "+longDingleThread); list.add(myCallableResponseModel1); list.add(myCallableResponseModel2); list.add(responseModel); list.add(studentList); log.info("current ---- end "); return new ResponseModel("多线程测试完成", 200, list); } }
测试案例
POSTMan测试
控制台打印
2022-07-02 01:48:37.521 INFO current ---- start 【http-nio-8081-exec-2】【CurrentController:34】 2022-07-02 01:48:39.552 INFO 多线程执行用时为: 2144 【http-nio-8081-exec-2】【CurrentController:60】 2022-07-02 01:48:43.588 INFO 单线程执行用时为: 4028 【http-nio-8081-exec-2】【CurrentController:67】 2022-07-02 01:48:43.589 INFO current ---- end 【http-nio-8081-exec-2】【CurrentController:73】
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/270967.html