SpringBoot多线程执行task任务

一.问题描述

  Task定时任务默认都是使用单线程执行的,如果定时任务有很多的话,那么可能会导致很多任务无法按时准确执行,示例如下:

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TaskTest {
    private final Logger log = LoggerFactory.getLogger(TaskTest02.class);
    //输出时间格式
    private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:sss");

    @Scheduled(cron = "0/15 * * * * ? ")
    private void sayHello(){
        String dateTime = format.format(new Date());
        log.info("{} 向宇宙发出了一声问候: Hello World!", dateTime);
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Scheduled(cron = "0/16 * * * * ? ")
    private void sayHello2(){
        String dateTime = format.format(new Date());
        log.info("{} 向宇宙发出了一声问候: 你好,世界", dateTime);
    }
}

当sayHello()方法执行的时候,因为长时间占用任务执行线程,导致sayHello2()被迫向后延时执行,如图:

二.解决方案

方案1

添加以下代码块,可放置在任意一个类中,整个工程只需要添加一个即可

@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    // 设置scheduler执行线程为3个
    scheduler.setPoolSize(3);
    return scheduler;
}

方案2(个人推荐)

添加一个配置类即可,定时任务类或方法不用做任何改变

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

/**
 * @描述: 多线程执行定时任务
 * @日期 2019年5月28日
 */
@Configuration
public class TaskConfig {
    /**
     * @描述: 所有的定时任务都放在一个线程池中,定时任务启动时使用不同的线程
     * @return
     * @日期 2019年5月28日
     */
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        // 设置scheduler执行线程为3个
        scheduler.setPoolSize(3);
        return scheduler;
    }
}
方案3

添加一个配置类即可(实现SchedulingConfigurer接口),定时任务类或方法不用做任何改变

import java.util.concurrent.Executors;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
 * @描述: 多线程执行定时任务
 * @日期 2019年5月27日
 */
@Configuration
public class SchedulingConfig implements SchedulingConfigurer {
    /**
     * @描述: 所有的定时任务都放在一个线程池中,定时任务启动时使用不同的线程
     * @param taskRegistrar
     * @日期 2019年5月27日
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //设定一个定时任务线程池,数量为3
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(3));
    }
}

三.执行结果

可以看到两个定时任务已经分别由不同的线程执行了

原文地址:https://blog.51cto.com/1197822/2401581

时间: 2024-08-30 01:28:27

SpringBoot多线程执行task任务的相关文章

springboot 多线程执行

一.springboot开线程执行异步任务 1.Spring通过任务执行器TaskExecutor,来实现多线程和并发编程,使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor; 2.异步需要在配置类上面加@EnableAsync 来开启对异步任务的支持在需要异步执行的方法上面加@Async 来声明这个方法是一个需要异步执行的方法; 3.让配置类实现AsyncConfigurer接口,并重写getAsyncExecutor方法,并返回一个ThreasPo

java多线程执行任务,处理共享成员变量的安全问题

java多线程执行任务时,为了避免任务的重复执行,可以通过synchronized关键字处理共享成员变量,具体代码如下: // 多线程处理任务方法 private void processMultiTask(final List<LogStatTask> list, int threadCount) throws Exception { // 根据设定的线程数处理任务列表 for (int i = 0; i < threadCount; i++) { TaskThread thread

.Net 多线程 (1) Task

多线程是一种有效提高程序工作效率的方法.当然为了效率需要使用更多的cpu,内存等资源. 并发是两个队列交替使用一台咖啡机,并行是两个队列同时使用两台咖啡机,如果串行,一个队列使用一台咖啡机,那么哪怕前面那个人便秘了去厕所呆半天,后面的人也只能死等着他回来才能去接咖啡,这效率无疑是最低的. 并发和并行都可以是很多个线程,就看这些线程能不能同时被(多个)cpu执行,如果可以就说明是并行,而并发是多个线程被(一个)cpu 轮流切换着执行. 运行一个线程 1 class Program 2 { 3 st

python之多线程执行和非线程执行的对比

一.非线程执行(普通的执行) 1.非线程运行,简单代码如下 #_*_coding:utf-8_*_ import time import threading a = [] b = [] def func1():     print "func1 start %s" % time.ctime()     alist = ["192.168.1.100","192.168.1.120","192.168.1.134","

java多线程执行问题

class Demo extends Thread{ public Demo(String name){ super(name); } public void run(){ for(int i=0; i<6; ++i){ System.out.println("i = " + i + "......Thread=" + Thread.currentThread().getName()); try{ Thread.sleep(100); }catch(Inter

关于多线程执行显示进度条的实例(转)&amp;&amp;线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。

关于多线程执行显示进度条的实例! 之前回答了一篇关于怎么在线程中操作进度条的帖子,估计有人看的不是很明白今天没事,写了一个小小的实例,很简单,就2个文件权当抛砖引玉,希望有更好解决方案的人发表一下意见 界面上2个控件,一个按钮和一个进度条using System;using System.Threading;using System.Windows.Forms; namespace WindowsFormsApplication2{    public partial class Form1 :

批处理实现多线程执行命令列表文件

批处理实现多线程执行命令列表 工作中碰到多线程执行命令列表的情况,研究一番,编写出来与大家分享.高手看了也请指点,指教一些更简单的办法. 批处理是一种单线程的简单脚本,只有上条命令执行完后,才能执行下条命令.如果上条命令执行花费很长时间,如超时,连接失败不断尝试等,下一条命令头发白了,可能还等不到它执行. 百度问答上找到一个方法可以实现多线程,原理:利用bat调用bat来实现多线程. 例如:网管希望同时ping局域中所有主机,实现方法如下. 首先,建立两个批处理文件: 1.bat文件代码如下:

【多线程】 Task

一. 常用方法: 1. ContinueWith : 当前 Task 完成后, 执行传入的 Task 2. Delay : 创建一个等待的 Task,只有在调用 Wait 方法时才会阻塞 (注意:与 Thread.Sleep 不同) 3. Run : 创建一个 Task 并执行 4. Start : 执行 Task 5. Wait : 在一定时间内阻塞线程, 直到 Task 完成或超过等待时间时取消阻塞 6. WaitAll : 阻塞线程直到所有的 Task 完成或超过等待时间 7. WaitA

spark DAGScheduler、TaskSchedule、Executor执行task源码分析

摘要 spark的调度一直是我想搞清楚的东西,以及有向无环图的生成过程.task的调度.rdd的延迟执行是怎么发生的和如何完成的,还要就是RDD的compute都是在executor的哪个阶段调用和执行我们定义的函数的.这些都非常的基础和困难.花一段时间终于弄白了其中的奥秘.总结起来,以便以后继续完善.spark的调度分为两级调度:DAGSchedule和TaskSchedule.DAGSchedule是根据job来生成相互依赖的stages,然后把stages以TaskSet形式传递给Task