SpringBoot 最简单的使用异步线程案例 @Async

简介: SpringBoot 最简单的使用异步线程案例 @Async

在网上找了很多很多资料,使用多线程、异步线程等等,很多配置,方法也多多;


那么,我向来都是以简单,够用为目标,下面我介绍的就是我认为已经非常非常简单的异步线程使用的方法了。

 

说到简单,当然是使用注解。


进入正题:


先上个目录结构:


image.png


好了,我们这次是在springboot里面使用的,不用导啥包。


我们先创个异步线程的配置类, 我的叫ThreadConfig,你们随意:


package com.async.config;
import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@ComponentScan("com.async.service")
@EnableAsync
public class ThreadConfig  {
    /**
     * 执行需要依赖线程池,这里就来配置一个线程池
     * @return
     */
    // 当池子大小小于corePoolSize,就新建线程,并处理请求
    // 当池子大小等于corePoolSize,把请求放入workQueue(QueueCapacity)中,池子里的空闲线程就去workQueue中取任务并处理
    // 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
    // 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁
   @Bean("getExecutor")
    public Executor getExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置核心线程数
        executor.setCorePoolSize(10);
        //设置最大线程数
        executor.setMaxPoolSize(100);
        //线程池所使用的缓冲队列
        executor.setQueueCapacity(250);
        //设置线程名
        executor.setThreadNamePrefix("JcTest-Async");
        //设置多余线程等待的时间,单位:秒
        //executor.setKeepAliveSeconds();
        // 初始化线程
        executor.initialize();
        return executor;
    }
}


向来我都不做代码过多的解释,因为我的代码注释 已!经!足!够!详!细 ! 了!

不过还是得提一下这俩注解,


@ComponentScan("com.async.service") 这个是告诉全世界,我即将开启异步线程的业务方法是哪个


@EnableAsync 这个! 必须有!  告诉全世界允许我使用异步线程


好了,接下来我们创建一下业务层的东西吧:


AsyncTestService:


package com.async.service;
public interface AsyncTestService {
    /**
     * 这里将会在impl里标注为异步任务,在执行此方法的时候,会单独开启线程来执行
     */
   void function1() throws InterruptedException;
    void function2();
}


AsyncTestServiceImpl:


package com.async.service.impl;
import com.async.service.AsyncTestService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class AsyncTestServiceImpl implements AsyncTestService {
    /**
     * 这里进行标注为异步任务,在执行此方法的时候,会单独开启线程来执行
     */
    @Async("getExecutor")
    public void function1() throws InterruptedException {
        System.out.println("f1 : " + Thread.currentThread().getName() + "   " + UUID.randomUUID().toString());
//        try {
//            Thread.sleep(10000);
//            System.out.println("EEEE");
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        //故意等10秒,那么异步线程开起来,这样明显看到 2方法不用等1方法执行完再调用了
        Thread.sleep(10000);
        System.out.println("EEEE");
    }
    @Async("getExecutor")
    public void function2() {
        System.out.println("f2 : " + Thread.currentThread().getName() + "   " + UUID.randomUUID().toString());
        try {
            Thread.sleep(100);
            System.out.println("aaaa");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


代码不走读了,但是必须得提下注解:


@Async这个是告诉全世界,这里! 只要被调用,就是会开启一个异步线程。

至于后面加上("getExecutor"),是为了指定读取自己写的配置信息例如线程名称那些。

 

最后是TestController:


package com.async.test;
import com.async.service.AsyncTestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
    @Autowired
    AsyncTestService asyncTestService;
    @GetMapping("/test")
    public void test() throws InterruptedException {
//        for (int i = 0; i < 10; i++) {
//            asyncTestService.function1(); // 执行异步任务
//            asyncTestService.function2();
//        }
        asyncTestService.function1(); // 执行异步任务
        asyncTestService.function2();
    }
}


启动类没啥改变:


package com.async;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AsyncApplication {
    public static void main(String[] args) {
        SpringApplication.run(AsyncApplication.class, args);
    }
}


好了,跑一下:


image.png结合


代码看看,懂了吧应该。  


稍微解释一哈:


asyncTestService.function1(); // 执行异步任务


asyncTestService.function2();


本来按照正常,肯定是按顺序执行的,也就是先编译完方法1,输出所有东东,再到方法2;


然后我们配了异步,而且在方法1那边sleep了蛮久的, 所以你看到输出结果,显然方法2自己单飞了,并没有等方法1;


这结果是我们想要的。


最后提醒一下, 有没有发现,我这个例子分了好多层,而且连impl都分了的。其实不分那么细也没问题,但是!!!


有个需要注意的!  利用@Async注解的方法, 不能跟调用它的方法放在同个类里面!!!! 否则会循环依赖错误!!!


还有一个需要注意的,@Async所修饰的函数不要定义为static类型,这样异步调用不会生效!


好了,就到这吧。


相关文章
|
4月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
351 0
|
4月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
181 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
10天前
|
缓存 安全 Java
面试中的难题:线程异步执行后如何共享数据?
本文通过一个面试故事,详细讲解了Java中线程内部开启异步操作后如何安全地共享数据。介绍了异步操作的基本概念及常见实现方式(如CompletableFuture、ExecutorService),并重点探讨了volatile关键字、CountDownLatch和CompletableFuture等工具在线程间数据共享中的应用,帮助读者理解线程安全和内存可见性问题。通过这些方法,可以有效解决多线程环境下的数据共享挑战,提升编程效率和代码健壮性。
37 6
|
1月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
109 17
|
1月前
|
存储 监控 Java
JAVA线程池有哪些队列? 以及它们的适用场景案例
不同的线程池队列有着各自的特点和适用场景,在实际使用线程池时,需要根据具体的业务需求、系统资源状况以及对任务执行顺序、响应时间等方面的要求,合理选择相应的队列来构建线程池,以实现高效的任务处理。
119 12
|
4月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
44 1
|
4月前
|
安全 调度 C#
STA模型、同步上下文和多线程、异步调度
【10月更文挑战第19天】本文介绍了 STA 模型、同步上下文和多线程、异步调度的概念及其优缺点。STA 模型适用于单线程环境,确保资源访问的顺序性;同步上下文和多线程提高了程序的并发性和响应性,但增加了复杂性;异步调度提升了程序的响应性和资源利用率,但也带来了编程复杂性和错误处理的挑战。选择合适的模型需根据具体应用场景和需求进行权衡。
|
4月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
124 0
|
5月前
|
设计模式 缓存 Java
谷粒商城笔记+踩坑(14)——异步和线程池
初始化线程的4种方式、线程池详解、异步编排 CompletableFuture
|
5月前
|
Java Spring
运行@Async注解的方法的线程池
自定义@Async注解线程池
210 3

热门文章

最新文章