接口经常超时?线程池+ FutureTask来解决!

简介: 接口经常超时?线程池+ FutureTask来解决!
  • 解决方案
  • 线程池 + FutureTask执行多任务计算
  • 子线程出的异常抛不出的情况

之前红包权益领取查询的接口超时了,因为有用户订购的权益有点多

解决方案

用线程池+ FutureTask将1个查询拆分成多个小查询 选择FutureTask是因为它具有仅执行1次run()方法的特性(即使有多次调用也只执行1次),避免了重复查询的可能。而且多任务异步执行也能提高接口响应速度。

本文主要讲的是线程池搭配FutureTask异步执行的例子

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

线程池 + FutureTask执行多任务计算

public class Test {
 //线程池最好作为全局变量, 若作为局部变量记得用完后shutdown()
 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-start-runner-%d").build();
 ExecutorService taskExe= new ThreadPoolExecutor(10,20,800L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(100),namedThreadFactory);
 int count=0;
 @Test
 public void test(String[] args) {
  //任务列表
  List<FutureTask<Integer>> taskList=new ArrayList<FutureTask<Integer>>();
  for(int i=0;i<100;i++){
   //创建100个任务放入【任务列表】
   FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
     return 1;
    }
   });
   //执行的结果装回原来的FutureTask中,后续直接遍历集合taskList来获取结果即可
   taskList.add(futureTask);
   taskExe.submit(futureTask);
  }
  //获取结果
  try{
   for(FutureTask<Integer> futureTask:taskList){
                count+=futureTask.get();
            }
  } catch (InterruptedException e) {
   logger.error("线程执行被中断",e);
  } catch (ExecutionException e) {
   logger.error("线程执行出现异常",e);
  }
  //关闭线程池
  taskExe.shutdown();
  //打印: 100
  System.out.println(count);
 }
}

Callable接口能让我们拿到线程的执行结果,所以让它作为FutureTask构造函数FutureTask(Callable<V> callable)的入参。

FutureTask执行的结果会放入它的私有变量outcome中,其他线程直接调用futureTask.get()去读取该变量即可

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

项目地址:https://github.com/YunaiV/onemall

子线程出的异常抛不出的情况

submit(Runnable task)提交任务的方式 ,是存在“隐患”的:

FutureTask内部的run()代码块会把异常给吞进去,通过setException(Throwable t)把异常赋给了对象outcome,我们在调用FutureTask.get()获取结果的时候返回的就是这个对象

如果你的代码没有调用FutureTask.get(),它不会把异常吐出来,有可能子线程就莫名的停止了。

public Future<?> submit(Runnable task) {
 if (task == null) throw new NullPointerException();
 //创建一个异步执行的任务FutureTask, 【隐患】也在它的run()代码块里
 RunnableFuture<Void> ftask = newTaskFor(task, null);
 execute(ftask);
 return ftask;
}

子线程创建之后会执行的是FutureTask内部的run()代码块,run()内部会有try-catch来截获抛出的异常,将其赋值给对象outcome

上面的例子没有这个问题,因为调用了FutureTask.get(),有异常会从这里拿出来

相关文章
|
10月前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
181 7
|
11月前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
186 6
|
安全 Java
在 Java 中使用实现 Runnable 接口的方式创建线程
【10月更文挑战第22天】通过以上内容的介绍,相信你已经对在 Java 中如何使用实现 Runnable 接口的方式创建线程有了更深入的了解。在实际应用中,需要根据具体的需求和场景,合理选择线程创建方式,并注意线程安全、同步、通信等相关问题,以确保程序的正确性和稳定性。
486 11
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
159 4
|
Java
java线程接口
Thread的构造方法创建对象的时候传入了Runnable接口的对象 ,Runnable接口对象重写run方法相当于指定线程任务,创建线程的时候绑定了该线程对象要干的任务。 Runnable的对象称之为:线程任务对象 不是线程对象 必须要交给Thread线程对象。 通过Thread的构造方法, 就可以把任务对象Runnable,绑定到Thread对象中, 将来执行start方法,就会自动执行Runable实现类对象中的run里面的内容。
109 1
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
236 3
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
244 2
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
193 2
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
299 1

热门文章

最新文章