0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SpringBoot实现多线程

jf_96884364 来源:jf_96884364 作者:jf_96884364 2023-01-12 16:59 次阅读

代码地址:https://github.com/Snowstorm0/learn-async

1 线程同步和异步

线程同步 :A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A只能等待下去。耗时较长,安全性较高。

线程异步 :A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到。

一个进程启动的多个不相干的进程,他们之间的相互关系为异步;同步必须执行到底后才能执行其他操作,异步可同时执行。

多个线程执行的时候需要同步,如果是单线程则不需要同步。

2 异步实例

主方法和被调用的方法必须是不同的类,才能实现多线程。

2.1 启动类

使用@EnableAsync来开启 SpringBoot 对于异步任务的支持。

Application:

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2.2 线程池

配置类实现接口AsyncConfigurator,返回一个ThreadPoolTaskExecutor线程池对象。

config/AsyncConfig:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    // ThredPoolTaskExcutor的处理流程
    // 当池子大小小于corePoolSize,就新建线程,并处理请求
    // 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
    // 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
    // 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁

    @Override
    @Bean
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数:线程池创建的时候初始化的线程数
        executor.setCorePoolSize(10);
        // 最大线程数:线程池最大的线程数,只有缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(100);
        // 缓冲队列:用来缓冲执行任务的队列
        executor.setQueueCapacity(50);
        // 线程池关闭:等待所有任务都完成再关闭
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 等待时间:等待5秒后强制停止
        executor.setAwaitTerminationSeconds(5);
        // 允许空闲时间:超过核心线程之外的线程到达60秒后会被销毁
        executor.setKeepAliveSeconds(60);
        // 线程名称前缀
        executor.setThreadNamePrefix("learn-Async-");
        // 初始化线程
        executor.initialize();
        return executor;
    }

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

2.3 controller

通过该层调用测试 Async。

@RestController
@RequestMapping("/homepage")
public class AsyncController {
    @Autowired
    AsyncService asyncTaskService;
    @GetMapping("/learnAsync")
    public String learnAsync(){
        for (int i = 0; i < 10; i++) {
            asyncTaskService.executeAsyncTask(i);
        }
        return "1";
    }
}

2.4 service

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

@Service
public class AsyncService {
    private final static Logger logger = LoggerFactory.getLogger(com.spring.boot.service.AsyncService.class);
    @Async  // 表明该方法是异步方法。如果注解在类上,那表明类里面的所有方法都是异步
    public void executeAsyncTask(int i) {
        logger.info("\\t 完成任务" + i);
        System.out.println("线程" + Thread.currentThread().getName() + " 执行异步任务:" + i);
    }
}

2.5 输出

3 Future 类

修改service层,分别使用同步调用、异步调用无返回、异步调用使用 Future 返回。

3.1 同步调用

public long subBySync() throws Exception {
    long start = System.currentTimeMillis();
    long sum = 0;
    long end = System.currentTimeMillis();
    sum = end - start;
    return sum;
}

3.2 异步调用无返回

@Async
public void subByVoid() throws Exception {
    long start = System.currentTimeMillis();
    long sum = 0;
    long end = System.currentTimeMillis();
    sum = end - start;
}

3.3 异步调用 Future 返回

controller:

Future task = asyncTaskService.subByAsync();

service:

@Async
public Future subByAsync() throws Exception {
    long start = System.currentTimeMillis();
    long sum = 0;
    long end = System.currentTimeMillis();
    sum = end - start;
    return new AsyncResult<>(sum);
}

4 CompletableFuture 类

若使用 Future 出现报错:

无法判断org.springframework.scheduling.annotation.AsyncResult<>的类型参数

不存在类型变量V的实例,使org.springframework.scheduling.annotation.AsyncResult符合XXX

可以使用 CompletableFuture 类:

@Asyncpublic 
CompletableFuture> subByAsyncMap() throws Exception {
    Map res = new HashMap<>();
    return CompletableFuture.completedFuture(res);
}

5 线程关闭

当线程数量超过核心线程数量之后,运行完毕的旧的线程会被关闭。

可以通过定时任务测试。

batch/ScheduledTaskService:

@Component
@EnableScheduling
public class ScheduledTaskService {
    @Autowired
    AsyncService asyncService;
    @Scheduled(cron = "1/1 * * * * ? ")  //1s一次
    public void learnCron(){
        asyncService.learnScheduledAsync();
    }
}

在 AsyncService 添加方法:

// 使用定时任务调用此方法创建线程
@Async
public void learnScheduledAsync(){
    Long timeLong = System.currentTimeMillis();
    SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置格式
    String timeString = timeFormat.format(timeLong);
    System.out.println("线程" + Thread.currentThread().getName());
    System.out.println("timeString:" + timeString + "\\n");
}

在异步配置(AsyncConfig)中已设置核心线程数为10:

// 核心线程数:线程池创建的时候初始化的线程数
executor.setCorePoolSize(10);

运行可以观察输出,线程数达到10后会再一次从1开始。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2904

    浏览量

    102994
  • 多线程
    +关注

    关注

    0

    文章

    271

    浏览量

    19724
  • spring
    +关注

    关注

    0

    文章

    332

    浏览量

    14161
  • Boot
    +关注

    关注

    0

    文章

    142

    浏览量

    35245
  • SpringBoot
    +关注

    关注

    0

    文章

    172

    浏览量

    106
收藏 人收藏

    评论

    相关推荐

    Java多线程的用法

    能力。 什么是进程 是指正在运行的程序的实例。 每个进程都拥有自己的内存空间、代码、数据和文件等资源,可以独立运行、调度和管理。在操作系统中,进程是系统资源分配的最小单位,是实现多任务的基础。 Java多线程 Java多线程是指
    的头像 发表于 09-30 17:07 621次阅读

    多线程解决思路一

    使用方法节点实现多线程,两个线程之间的数据传输也都使用方法节点的方式实现。1、初始化时打开另一个线程。2、程序运行过程中
    发表于 07-06 17:21

    51单片机多线程实现

    51单片机多线程实现,给STC89C52RC单片机移植RTX-Tiny操作系统,简单到爆,B格拉满了,好吧?
    发表于 07-14 06:43

    浅析Python使用多线程实现串口收发数据

    Python使用多线程实现串口收发数据前言代码最后前言近期要写个串口的代码,想着工程有点大打算用多线程布局…在使用这份代码之前,
    发表于 08-24 07:49

    利用线程的互斥实现串口多线程收发数据

    利用线程的互斥实现串口多线程收发数据从而达到流水灯的效果。多线程串口编程主要分为三步,第一部分,连接串口及开发板,确定设备号;第二部分为串口参数的设置;第三部分为
    发表于 01-07 08:08

    PC机与嵌入式系统的多线程串行通信实现

    述了PC 机与嵌入式计算机系统的多线程串行通信的实现。介绍了多线程设计思想的必要性,给出了程序设计流程。
    发表于 08-29 08:50 32次下载

    多线程技术在串口通信中的应用

            首先介绍了多线程技术的基本原理,然后讨论了多线程技术在串口通信中的应用,并给出了实现的方法和步骤。关键词:
    发表于 09-04 09:10 18次下载

    Delphi教程_实现多线程共享探测

    Delphi教程实现多线程共享探测,很好的Delphi学习资料。
    发表于 03-16 14:59 3次下载

    基于OPC技术的多线程数据采集系统的实现_乔富强

    基于OPC技术的多线程数据采集系统的实现_乔富强
    发表于 01-12 19:56 1次下载

    多线程与聊天室程序的创建

    多线程程序的编写,多线程应用中容易出现的问题。互斥对象的讲解,如何采用互斥对象来实现多线程的同步。如何利用命名互斥对象保证应用程序只有一个实例运行。应用
    发表于 05-16 15:22 0次下载

    多线程好还是单线程好?单线程多线程的区别 优缺点分析

    摘要:如今单线程多线程已经得到普遍运用,那么到底多线程好还是单线程好呢?单线程多线程的区别又
    发表于 12-08 09:33 8w次阅读

    什么是多线程编程?多线程编程基础知识

    摘要:多线程编程是现代软件技术中很重要的一个环节。要弄懂多线程,这就要牵涉到多进程。本文主要以多线程编程以及多线程编程相关知识而做出的一些结论。
    发表于 12-08 16:30 1.2w次阅读

    Java多线程永动任务 多线程异步任务项目解读

    1. 功能说明 2. 多线程任务示例 2.1 线程池 2.2 单个任务 2.3 任务入口 2.4 结果分析 2.5 源码地址 3. 写在最后 大家好,今天教大家撸一个 Java 的多线程永动任务
    的头像 发表于 10-19 11:46 791次阅读

    mfc多线程编程实例

    (图形用户界面)应用程序的开发。在这篇文章中,我们将重点介绍MFC中的多线程编程。 多线程编程在软件开发中非常重要,它可以实现程序的并发执行,提高程序的效率和响应速度。MFC提供了丰富的多线程
    的头像 发表于 12-01 14:29 505次阅读

    java实现多线程的几种方式

    Java实现多线程的几种方式 多线程是指程序中包含了两个或以上的线程,每个线程都可以并行执行不同的任务或操作。Java中的
    的头像 发表于 03-14 16:55 175次阅读