SpringBoot中使用多线程的方法示例

 更新时间:2021年03月17日 09:32:39   作者:BouncingFish  
这篇文章主要介绍了SpringBoot中使用多线程的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、介绍

Spring是通过任务执行器(TaskExecutor)来实现多线程和并发编程,使用Spring提供的ThreadPoolTaskExecutor来创建一个基于线城池的TaskExecutor。在使用线程池的大多数情况下都是异步非阻塞的。节省更多的时间,提高效率。

工作原理

当主线程中调用execute接口提交执行任务时:则执行以下步骤:注意:线程池初始时,是空的。

  • 如果当前线程数<corePoolSize,如果是则创建新的线程执行该任务
  • 如果当前线程数>=corePoolSize,则将任务存入BlockingQueue
  • 如果阻塞队列已满,且当前线程数<maximumPoolSize,则新建线程执行该任务。
  • 如果阻塞队列已满,且当前线程数>=maximumPoolSize,则抛出异常RejectedExecutionException,告诉调用者无法再接受任务了。

在Springboot中对其进行了简化处理,只需要配置一个类型为java.util.concurrent.TaskExecutor或其子类的bean,并在配置类或直接在程序入口类上声明注解@EnableAsync,即可可以开启异步任务。

调用也简单,在由Spring管理的对象的方法上标注注解@Async,声明是异步任务,显式调用即可生效。

二、声明

让配置类实现AsyncConfigurer接口,并重写getAsyncExecutor方法,并返回一个ThreasPoolTaskExecutor,就可以获取一个基于线程池的TaskExecutor
使用注解@EnableAsync开启异步,会自动扫描

@Configuration
@EnableAsync
public class ThreadConfig implements AsyncConfigurer {

  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(15);
    executor.setQueueCapacity(25);
    executor.initialize();
    return executor;
  }

  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return null;
  }
}

三、调用

通过@Async注解表明该方法是异步方法,如果注解在类上,那表明这个类里面的所有方法都是异步的

@Service
public class AsyncTaskService {

  @Async
  public void executeAsyncTask(int i) {
    System.out.println("线程" + Thread.currentThread().getName() + " 执行异步任务:" + i);
  }

}

四、进阶

有时候我们不止希望异步执行任务,还希望任务执行完成后会有一个返回值,在java中提供了Future泛型接口,用来接收任务执行结果,springboot也提供了此类支持,使用实现了ListenableFuture接口的类如AsyncResult来作为返回值的载体。比如上例中,我们希望返回一个类型为String类型的值,可以将返回值改造为:

  @Async
  public Future<String> executeAsyncTaskWithResult2(int i) {
    System.out.println("线程" + Thread.currentThread().getName() + " 开始执行异步任务" + i);
    try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("线程" + Thread.currentThread().getName() + " 结束执行异步任务" + i);
    return new AsyncResult<>("线程" + Thread.currentThread().getName() + " 执行异步任务:" + i);
  }

调用返回值:
get()是阻塞式,等待当前线程完成才返回值

  public void threadTest() {
    try {
      List<Future> futures = new ArrayList<>();
      for (int i = 0; i < 20; i++) {
        futures.add(asyncTaskService.executeAsyncTaskWithResult2(i));
      }
      // 获取值。get是阻塞式,等待当前线程完成才返回值
      for (Future<String> future : futures) {
        System.out.println("返回结果:" + future.get());
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
  }

补充

实际上,@Async还有一个参数,通过Bean名称来指定调用的线程池-比如上例中设置的线程池参数不满足业务需求,可以另外定义合适的线程池,调用时指明使用这个线程池-缺省时springboot会优先使用名称为'taskExecutor'的线程池,如果没有找到,才会使用其他类型为TaskExecutor或其子类的线程池。

到此这篇关于SpringBoot中使用多线程的方法示例的文章就介绍到这了,更多相关SpringBoot使用多线程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaWeb 实现验证码功能(demo)

    JavaWeb 实现验证码功能(demo)

    在 WEB-APP 中一般应用于:登录、注册、买某票、秒杀等场景,大家都接触过这个验证码操作,今天小编通过实例代码给大家讲解javaweb实现验证码功能,需要的朋友参考下
    2017-02-02
  • java为什么需要虚拟机jvm原理详解

    java为什么需要虚拟机jvm原理详解

    这篇文章主要为大家介绍了java为什么需要虚拟机jvm的原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-11-11
  • Java的动态绑定与双分派_动力节点Java学院整理

    Java的动态绑定与双分派_动力节点Java学院整理

    这篇文章主要介绍了Java的动态绑定与双分派,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java经典面试题之NIO多路复用

    Java经典面试题之NIO多路复用

    JAVA NIO 的多路复用是面试中经常被问的问题,今天我们彻底搞明白究竟是怎么回事,文中的示例代码讲解详细,希望对大家学习Java有所帮助
    2023-06-06
  • 使用Runtime 调用Process.waitfor导致的阻塞问题

    使用Runtime 调用Process.waitfor导致的阻塞问题

    这篇文章主要介绍了使用Runtime 调用Process.waitfor导致的阻塞问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot最简洁的国际化配置

    SpringBoot最简洁的国际化配置

    这篇文章主要介绍了SpringBoot最简洁的国际化配置,Spring Boot是一个用于构建独立的、生产级别的Spring应用程序的框架,国际化是一个重要的功能,它允许应用程序根据用户的语言和地区显示不同的内容,在Spring Boot中,实现国际化非常简单,需要的朋友可以参考下
    2023-10-10
  • SpringBoot Mybatis批量插入Oracle数据库数据

    SpringBoot Mybatis批量插入Oracle数据库数据

    这篇文章主要介绍了SpringBoot Mybatis批量插入Oracle数据库数据,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • RocketMQ源码本地搭建调试方法

    RocketMQ源码本地搭建调试方法

    这篇文章主要介绍了RocketMQ源码本地搭建调试,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • 浅析java中Pair和Map的区别

    浅析java中Pair和Map的区别

    这篇文章主要介绍了java中Pair和Map的区别,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • java图论弗洛伊德和迪杰斯特拉算法解决最短路径问题

    java图论弗洛伊德和迪杰斯特拉算法解决最短路径问题

    这篇文章主要为大家介绍了java图论弗洛伊德算法和迪杰斯特拉算法解决最短路径的问题示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11

最新评论