SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析

同步编程&异步编程

Java并发编程中,同步和异步是两种常见的处理方式。

同步是指多个任务按顺序执行,一个任务的执行需要等待上一个任务的完成。而异步则是指多个任务可以并行执行,不需要等待上一个任务完成。

在多线程编程中,同步是指多个线程按顺序执行,一个线程的执行需要等待上一个线程的完成;而异步是指多个线程可以并发执行,不需要等待其他线程的完成。

在实际应用中,同步通常适用于简单的线性任务,比如IO操作、数据库读写等;而异步通常适用于复杂的并发任务,比如并行计算、大规模数据处理等。

线程池

为什么要使用线程池?

当创建使用线程,需要进行new Thread操作,在JVM的堆内存中创建新的对象地址。

当使用完毕后,需要等待JVM的GC操作,检索Root根释放堆中的垃圾信息。

频繁的创建线程和销毁垃圾,极大的消耗了系统的资源,降低了处理其他业务的性能问题。

创建一个池,保存初始化的线程,用的时候取,不用的时候放入池中等待下次使用。

减少创建的线程数。

Spring自定义线程池

/**
 * @author linghu
 * 自定义线程池配置
 * 需要使用线程池,则开启当前配置
 */
@Configuration
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolExecutor myThreadPool(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,//核心线程数,一直都能工作的数量
                5,//请求处理大的时候,可以开放的最大工作数、最大线程数
                3,//开启最大工作数后,当无请求时,还让其存活的时间、线程活跃时间
                TimeUnit.SECONDS,//存活时间的单位
                new LinkedBlockingDeque<>(10),//阻塞队列,保存操作请求线程
                Executors.defaultThreadFactory(),//创建线程的工厂类
                new ThreadPoolExecutor.AbortPolicy()//设置拒绝策略
        );
        return threadPoolExecutor;
    }
}

具体案例:

@RestController
public class TestController {
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private MyService myService;
    @RequestMapping("/getThreadPoolInfo")
    public void getThreadPoolInfo(){
        System.out.println("getActiveCount--"+threadPoolExecutor.getActiveCount());
        System.out.println("getCorePoolSize--"+threadPoolExecutor.getCorePoolSize());
        System.out.println("getPoolSize--"+threadPoolExecutor.getPoolSize());
    }
    @RequestMapping("/test1")
    public String test1(){
        System.out.println("进入test1 "+System.currentTimeMillis());
        /** 这种调用其实比较复杂,还有更简单的调用法则 */
        threadPoolExecutor.execute(()->{
            try {
                System.out.println("线程池处理数据  start "+System.currentTimeMillis());
                TimeUnit.SECONDS.sleep(3);
                System.out.println("线程池处理数据  end "+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("线程池调用结束 "+System.currentTimeMillis());
        return "6666";
    }
}

测试:

上面自定义的线程池能够实现异步调用执行方法。

SpringBoot轻松调用线程池

SpringBoot自定义线程池同上面的Spring,只不过多了几个注解简化了一些操作。SpringBoot能够通过这个注解更轻松的调用线程池。

我们将类上添加注解@EnableAsync 开启异步调用,让在需要使用的地方,直接使用@Async就可以了。

@Configuration
@EnableAsync//注解开启异步调用Async
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolExecutor myThreadPool(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,//核心线程数,一直都能工作的数量
                5,//请求处理大的时候,可以开放的最大工作数、最大线程数
                3,//开启最大工作数后,当无请求时,还让其存活的时间、线程活跃时间
                TimeUnit.SECONDS,//存活时间的单位
                new LinkedBlockingDeque<>(10),//阻塞队列,保存操作请求线程
                Executors.defaultThreadFactory(),//创建线程的工厂类
                new ThreadPoolExecutor.AbortPolicy()//设置拒绝策略
        );
        return threadPoolExecutor;
    }
}

然后编写一个测试类,同时也需要将具体的异步业务单独独立出来:

@RequestMapping("/test2")
    public void test2() throws InterruptedException {
        System.out.println("进入test2 "+System.currentTimeMillis());
        myService.service1();
        System.out.println("调用结束 "+System.currentTimeMillis());
    }

服务类的代码如下所示:

// 具体使用哪个线程池
@Async("myThreadPoolExecutor")
public void service1() throws InterruptedException {
    System.out.println("----- service1 start --------"+System.currentTimeMillis());
    TimeUnit.SECONDS.sleep(3);
    System.out.println("----- service1 end --------"+System.currentTimeMillis());
}

执行请求:

http://localhost:8080/test2

总结

我们其实用注解 @Async("myThreadPoolExecutor")取代了

threadPoolExecutor.execute(()->{
            try {
                System.out.println("线程池处理数据  start "+System.currentTimeMillis());
                TimeUnit.SECONDS.sleep(3);
                System.out.println("线程池处理数据  end "+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

测试demo链接

https://gitee.com/xiangjiaobunana/springboot-thread-pool

目录
相关文章
|
8天前
|
缓存 Java 调度
多线程编程核心:上下文切换深度解析
在现代计算机系统中,多线程编程已成为提高程序性能和响应速度的关键技术。然而,多线程编程中一个不可避免的概念就是上下文切换(Context Switching)。本文将深入探讨上下文切换的概念、原因、影响以及优化策略,帮助你在工作和学习中深入理解这一技术干货。
27 10
|
8天前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
21 4
|
10天前
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
|
26天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
23天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
26天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
1月前
|
安全 程序员 API
|
1月前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
1月前
|
缓存 Java 调度
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文旨在为读者提供一个关于Java多线程编程的全面指南。我们将从多线程的基本概念开始,逐步深入到Java中实现多线程的方法,包括继承Thread类、实现Runnable接口以及使用Executor框架。此外,我们还将探讨多线程编程中的常见问题和最佳实践,帮助读者在实际项目中更好地应用多线程技术。
24 3
|
1月前
|
监控 安全 Java
Java多线程编程的艺术与实践
【10月更文挑战第22天】 在现代软件开发中,多线程编程是一项不可或缺的技能。本文将深入探讨Java多线程编程的核心概念、常见问题以及最佳实践,帮助开发者掌握这一强大的工具。我们将从基础概念入手,逐步深入到高级主题,包括线程的创建与管理、同步机制、线程池的使用等。通过实际案例分析,本文旨在提供一种系统化的学习方法,使读者能够在实际项目中灵活运用多线程技术。

推荐镜像

更多