多线程查询,效率翻倍

参考链接: 查询速度起飞之Java利用多线程进行并发数据查询_衡与墨的博客-CSDN博客_多线程并发查询数据库

代码案例

多线程工具类 提高执行线程和获取返回数据方法

/**
 * 多线程工具类
 */
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】

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
继“Java开发微信朋友圈PC版系统-架构1.0”之后,debug这段时间日撸夜撸,终于赶在春节放假前给诸位带来了这一系统的架构2.0版本,特此分享给诸位进行学习,以掌握、巩固更多的技术栈以及项目和产品开发经验,同时也为即将到来的金三银四跳槽季做准备! 言归正传,下面仍然以问答的方式介绍下本门课程的相关内容! (1)问题一:这是一门什么样的课程? 很明显,本门课程是建立在架构1.0,即 第1门课程 的基础上发布的,包含了架构1.0的内容,即它仍然是一门项目、产品实战课,基于Spring Boot2.X + 分布式中间件开发的一款类似“新浪微博”、“QQ空间”、“微信朋友圈”PC版的互联网社交软件,包含完整的门户网前端 以及 后台系统管理端,可以说是一套相当完整的系统! (2)问题二:架构2.0融入了哪些新技术以及各自有什么作用? 本课程对应着系统架构2.0,即第2阶段,主要目标:基于架构1.0,优化系统的整体性能,实现一个真正的互联网社交产品;其中,可以学习到的技术干货非常多,包括:系统架构设计、Spring Boot2.X、缓存Redis、多线程并发编程、消息中间件RabbitMQ、全文搜索引擎Elastic Search、前后端消息实时通知WebSocket、分布式任务调度中间件Elastic Job、Http Restful编程、Http通信OKHttp3、分布式全局唯一ID、雪花算法SnowFlake、注册中心ZooKeeper、Shiro+Redis 集群Session共享、敏感词自动过滤、Java8 等等; A.  基于Elastic Search实现首页列表数据的初始化加载、首页全文检索;B.  基于缓存Redis缓存首页朋友圈“是否已点赞、收藏、关注、评论、转发”等统计数据;整合Shiro实现集群部署模式下Session共享;C.  多线程并发编程并发处理系统产生的废弃图片、文件数据;D.  基于Elastic Job切片作业调度分布式多线程清理系统产生的废弃图片;E.  基于RabbitMQ解耦同步调用的服务模块,实现服务模块之间异步通信;F.  基于WebSocket实现系统后端 与 首页前端 当前登录用户实时消息通知;G.  基于OKHttp3、Restful风格的Rest API实现ES文档、分词数据存储与检索;H.  分布式全局唯一ID 雪花算法SnowFlake实现朋友圈图片的唯一命名;I.  ZooKeeper充当Elastic Job创建的系统作业的注册中心;J.  为塑造一个健康的网络环境,对用户发的朋友圈、评论、回复内容进行敏感词过滤;K.  大量优雅的Java8  Lambda编程、Stream编程;  (3)问题三:系统运行起来有效果图看吗?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值