SpringBoot项目多线程实现定时任务-只需要三步

news2024/11/27 20:29:35

众所周知,项目中需要使用定时任务发布的需求时非常常见的,例如:数据同步,清理垃圾文件,清理过期用户等需求,可能需要我们定时去清理数据。

但是我们如果集成xxl-job,Quartz,spring task等定时任务框架,但是我们如果只是针对某些小需求进行定时任务,完全用不到这样调度框架,Spring Boot框架中集成了@Schedule定时任务。

在我们使用@Schedule注解的时候,需要注意的时,这是一个单线程的定时任务,也就是说当我们在同一时间进行执行多个任务的时候,可能会出现第二个任务无法执行(不是绝对的)、任务执行顺序也不一样(有可能第一个任务先执行,也有可能是第二个任务先执行)。

所以在这里我们要想到使用多线程的方式。

第一步:pom文件修改

在我们创建完成springboot项目后,其实pom文件无需导入其他的依赖了,因为spring-boot-starter这个依赖中了。

第二步:配置ScheduleConfig

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableScheduling
@EnableAsync
public class SchedulingConfig {
    private final int corePoolSize=2;
    private final int maxPoolSize=10;
    private final int queueCapacity=25;
    private final String namePrefix="AsyncTask-";

    /**
     * 自定义线程池配置类。
     * 不要命名为 taskScheduler,与spring框架的bean重名。
     * @return
     */
    @Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        //阿里巴巴编程规范:线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

        //SpringBoot项目,可使用Spring提供的对 ThreadPoolExecutor 封装的线程池 ThreadPoolTaskExecutor:
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//        ThreadPoolTaskExecutor executor = new MyThreadPoolTaskExecutor();//自定义ThreadPoolTaskExecutor,会打印线程池情况
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        //     1、CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行。
        //        "该策略既不会抛弃任务,也不会抛出异常,而是将任务回推到调用者。"顾名思义,在饱和的情况下,调用者会执行该任务(而不是由多线程执行)
        //     2、AbortPolicy:拒绝策略,直接拒绝抛出异常
        //     3、。。。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
}

第三步:编写定时任务业务层代码

package com.example.demo.task;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.xml.crypto.Data;
import java.util.concurrent.Executor;


@Component
public class BusinessTaskScheduler {



    @Scheduled(cron = "0 0/1 * * * ?")
    @Async("asyncServiceExecutor")
    public void TelecomBusinessTask() {
        // 业务逻辑代码
        try {
            System.out.println("任务1执行时间:"+System.currentTimeMillis());
            for (int i = 0; i < 6; i++) {

                System.out.println("执行任务的线程名称: " + Thread.currentThread().getName()+"-----任务1");
            }
        } catch (Exception e) {
            throw new RuntimeException("获取定时任务调用失败!"+e);
        }
    }



    @Scheduled(cron = "0 0/1 * * * ?")
    @Async("asyncServiceExecutor")
    public void MobileBeiXiangTask() {
        try {
            System.out.println("任务2执行时间:"+System.currentTimeMillis());
            for (int i = 0; i < 6; i++) {
                System.out.println("执行任务的线程名称: " + Thread.currentThread().getName()+"-----任务2");
            }
        } catch (Exception e) {
            throw new RuntimeException("获取定时任务调用失败!"+e);
        }
    }

}

测试结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2060546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IPC 进程间通信方式

IPC对象(共享内存) 共享内存&#xff1a; 1.是一块&#xff0c;内核预留的空间 2.最高效的通信方式 //避免了用户空间 到 内核空间的数据拷贝 用中间那个get函数&#xff0c;就可以使key与共享内存一一对应 怎么将共享内存与进程关联起来 //step1 产生key值 ftok: 功能&am…

鸿蒙内核源码分析——(自旋锁篇)

本篇说清楚自旋锁 读本篇之前建议先读系列篇 进程/线程篇. 内核中哪些地方会用到自旋锁?看图: 概述 自旋锁顾名思义&#xff0c;是一把自动旋转的锁&#xff0c;这很像厕所里的锁&#xff0c;进入前标记是绿色可用的&#xff0c;进入格子间后&#xff0c;手一带&#xff0c…

「黑神话:悟空」员工疯狂被挖!打工天命人急改备注……

一部国产3A大作「黑神话:悟空」横空出世&#xff0c;震动了全球&#xff0c;冲上多国销量榜首。 尤其对于中国玩家以及中国游戏市场来说&#xff0c;这款产品实在让大家等了太久&#xff0c;最让人意外的是&#xff0c;昔日那些喊着电子鸦片的大媒体&#xff0c;也话风一转&…

高级列表组件ReList

高级列表组件ReList 组件实现基于 Vue3 Element Plus Typescript&#xff0c;同时引用 vueUse lodash-es tailwindCss (不影响功能&#xff0c;可忽略) 主要基于JSX风格实现高度动态的列表渲染组件&#xff0c;可以通过信息配置Metas配置控制信息项展示&#xff0c;同时支持…

数学基础(二)

一、导数 导数计算&#xff1a; 偏导数&#xff1a; 方向导数&#xff1a; 梯度&#xff1a; 函数在某点的梯度是一个向量&#xff0c;它的方向余方向导数最大值取得的方向一致。其大小正好是最大的方向导数 二、微积分 面积由来&#xff1a; 切线&#xff1a; 定积分&#x…

[Linux]如何在虚拟机安装Ubuntu?(小白向)

一、我们为什么要在虚拟机中安装Ubuntu? 在虚拟机中安装系统主要是为了让一个系统与我们原本的系统隔离&#xff0c;不管是想运行一些不安全的软件&#xff0c;或者是想运行一些独特的操作系统&#xff0c;我们都可以选择使用虚拟机来安装和隔离这些操作系统。如果你是一位Lin…

PMP–知识卡片--工作分解结构WBS元素

WBS包含如下几种元素&#xff1a; &#xff08;1&#xff09;子项目&#xff1a;子项目是整个项目的一部分&#xff0c;它可以被相对独立地作为“项目”进行管理&#xff0c;可以由一个专业团队或一个分包组织负责&#xff1b; &#xff08;2&#xff09;控制账户&#xff1a;控…

爆款来袭!AI萌娃T台秀,单条视频千万级播放量,制作方法竟如此简单!

大家好&#xff0c;我是小奇&#xff0c;一名热衷于分享AI副业项目的普通博主。不管你是AI小白还是老手&#xff0c;我都能帮你轻松上手&#xff0c;用AI技术赚钱。想多赚点&#xff1f;跟我来&#xff0c;一起探索AI副业&#xff0c;实现财务自由&#xff01;记得关注我哦&…

Java、python、php版的高校失物招领平台(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

数据结构(11)——二叉搜索树

欢迎来到博主的专栏&#xff1a;数据结构 博主ID:代码小豪 文章目录 二叉搜索树二叉搜索树的声明与定义二叉搜索树的查找二叉搜索树的插入二叉搜索树的中序遍历二叉搜索树的删除 key_value型搜索二叉树 二叉搜索树 二叉搜索树也称二叉排序树&#xff0c;是具备以下特征的二叉树…

sourceinsigt + samba

samba服务器 yum install -y sambsystemctl start smb systemctl enable smb 注意 setenforce 0 是一个用于管理 SELinux&#xff08;Security-Enhanced Linux&#xff09;模式的命令。SELinux 是 Linux 内核的一种安全模块&#xff0c;提供了强制访问控制&#xff08;MAC&am…

【密码学】密钥管理:②密钥分配

一、密钥分配的定义 密钥分配是密钥管理生命周期中最重要的部分&#xff0c;密钥分配方案研究的是密码系统中密钥的分发和传送问题。从本质上讲&#xff0c;密钥分配为通信双方建立用于信息加密、解密签名等操作的密钥&#xff0c;以实现保密通信或认证签名等。 &#xff08;1…

埃氏筛选法求素数

埃氏筛选法求素数可以减少遍历次数&#xff0c;及在前期的循环中就将存在的合数打上标记&#xff0c;从而提高算法的时间效率。 一、算法实现 void prime_number(int n) {int flag[n];int count 0;int* primeArr;/// 默认标记所有的数都是素数memset(flag,0,sizeof(flag…

浅析打电话检测算法接打电话识别算法展示及其全套打电话检测算法源码

打手机检测算法&#xff0c;特别是智能边缘分析一体机中的打手机检测算法&#xff0c;是一种专门用于监控和分析在边缘计算设备上的手机使用行为的算法。这种算法主要利用了机器学习和计算机视觉的先进技术&#xff0c;通过对设备上的视频流或图像进行深入分析&#xff0c;以识…

“万物共生”户外沉浸式展馆光影互动设计,思特科技打造!

01      思特科技助力北京玉渊潭公园 “万物共生” 户外沉浸式展馆光影互动设计&#xff0c;将公园独具特色的人文景观和自然景观相结合&#xff0c;利用数字光影艺术&#xff0c;通过不同形式、不同状态来表现生命的多元化&#xff0c;带来震撼的沉浸式体验。    北京…

加密与安全_解密AES加密中的IV和Seed

文章目录 概述IV&#xff08;Initialization Vector&#xff0c;初始化向量&#xff09;Seed&#xff08;种子&#xff09; CodeseedIV 小结 概述 在AES加密中&#xff0c;**IV&#xff08;Initialization Vector&#xff0c;初始化向量&#xff09;和Seed&#xff08;种子&am…

HoloLens 坐标系统 Coordinate systems

Hololens 和 Unity 空间坐标系统-CSDN博客文章浏览阅读79次。这意味着&#xff0c;在 X、Y 或 Z 轴上相距 2 个单位的物体&#xff0c;在混合现实中的渲染效果是相距 2 米。虽然左手坐标和右手坐标是最常见的系统&#xff0c;但 3D 软件中也会使用其他坐标系。例如&#xff0c;…

【杂乱算法】前缀和与差分

前缀和 文章目录 前缀和一维应用 二维差分一维 二维扩展1、前缀和与哈希表 一维 一个数组prefix中&#xff0c;第i个元素表示nums[0]至nums[i-1]的总和&#xff0c;那么我们就称这个prefix数组是nums数组的前缀和。 prefix [ i ] ∑ j 0 i nums [ j ] \text{prefix}[i] \s…

显示弹出式窗口的方法

文章目录 1. 概念介绍2. 使用方法3. 示例代码 我们在上一章回中介绍了Sliver综合示例相关的内容&#xff0c;本章回中将介绍PopupMenuButton组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中介绍的PopupMenuButton组件位于AppBar右侧&#xf…

x-cmd pkg | dua - 一个可以方便地了解给定目录的磁盘空间使用情况的工具

目录 简介用户首次快速实验指南技术特点竞品和相关项目进一步阅读 简介 dua 是 Disk Usage Analyzer 的简写&#xff0c;该工具可以快速查看给定目录的磁盘空间使用情况。 对于想要深入了解磁盘空间使用情况并有效管理存储的用户来说&#xff0c;Dua 是一个很有价值的工具。通…