2

多线程查询,效率翻倍 - hikoukay

 1 year ago
source link: https://www.cnblogs.com/hikoukay/p/16436349.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

参考链接: 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测试

1196335-20220702020747930-155960069.png

控制台打印

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】

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK