JAVA多线程(四) Executor并发框架向RabbitMQ推送消息
github代码地址: https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service
假设一个需求用户点击某个页面,我们后台需要向MQ推送信信息
1,模拟的MQ服务,我这边使用RabbitMQ (关于MQ 发送和监听消息可以参考我的博客:SpringBoot消息中间件RabbitMQ)
//后台监听消息
@RabbitListener(queues = "brian.test") public void receiveMessage(User user){ logger.info("接收到MQ的消息体: " + user); }
2.向IOC容器中注册一个ThreadPoolTaskExecutor实例
@Bean public ThreadPoolTaskExecutor brianThreadPool(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程数 executor.setCorePoolSize(8); //最大线程数 executor.setMaxPoolSize(16); //队列中最大的数 executor.setQueueCapacity(8); //县城名称前缀 executor.setThreadNamePrefix("brianThreadPool_"); //rejectionPolicy:当pool已经达到max的时候,如何处理新任务 //callerRuns:不在新线程中执行任务,而是由调用者所在的线程来执行 //对拒绝task的处理策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //线程空闲后最大的存活时间 executor.setKeepAliveSeconds(60); //初始化加载 executor.initialize(); return executor; }
3.实现线程池并发推送消息
/** * 多线程推送消息到MQ服务 */ public void sendMessageByThredPool(User user) throws ExecutionException, InterruptedException { Future<String> future = executor.submit(() -> { sendMessageService.sendMessage("brian","mymq",user);
logger.info("线程 [ " + Thread.currentThread().getName() + " ] 推送消息到MQ成功! " + new Date()); return Thread.currentThread().getName(); }); }
4. Controller层的调用
@PostMapping("/loop/sendMsg/userInfo") public ResponseEntity addUserInfo2MQ(@RequestBody User user) throws ExecutionException, InterruptedException { brianService.sendMessageByThredPool(user); return new ResponseEntity(user, HttpStatus.OK); }
5.利用postman 做压力测试,测试接口
5.1 postman做loop压力测试,需要单创建一个Collections来测试,并且当前Collections值允许放一个测试用例,比如我下面的loopSendUserInfo
5.2 设置测试规则
点击Preview ,可以预览测试数据
6.查看测试结果
6.1 rabbitmq
6.2 log中可以发现多个线程在推送消息
博客参考来源:1. 可取消的异步任务——FutureTask用法及解析
2. 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture