spring-boot @scheduled无法在其他线程中运行? [英] spring-boot @scheduled not running in different threads?

查看:258
本文介绍了spring-boot @scheduled无法在其他线程中运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在配置计划任务以在不同线程中运行. 这是配置代码

I am configuring a scheduled task to run in different threads. Here is the configuration code

@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {
    private final int POOL_SIZE = 10;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
        threadPoolTaskScheduler.setThreadNamePrefix("my-sched-pool-");
        threadPoolTaskScheduler.initialize();
        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}

这是使用它的代码

@Scheduled(fixedRateString = "2000" )
    public void testaMethod() {

         log.debug("here is the message");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

我正在将线程休眠10s,fixedRate为2s.所以我希望在日志中看到不同的线程 但我只看到一个

I am sleeping the thread for 10s with fixedRate of 2s. so I expect to see different threads in the log but I see only one

日志在这里

{"thread":"my-sched-pool-1","level":"DEBUG","description":"here is the message"}
{"thread":"my-sched-pool-1","level":"DEBUG","description":"here is the message"}
{"thread":"my-sched-pool-1","level":"DEBUG","description":"here is the message"}
{"thread":"my-sched-pool-1","level":"DEBUG","description":"here is the message"}

推荐答案

@Scheduled(fixedRateString = "2000" )不保证每2秒执行一次testaMethod,如果时间成本超过2s,例如Thread.sleep(10000),则新任务将被排入队列.仅在执行旧任务时,调度程序才会从队列中获取新任务并执行它.由于新任务现在是调度程序中的唯一任务,因此可以在不创建新Thread的情况下运行它.

@Scheduled(fixedRateString = "2000" ) does not gurantee testaMethod be executed every 2 seconds, if the time cost is more than 2s, such as Thread.sleep(10000), the new task will be put in a queue. Only when the old one has been executed, the scheduler will fetch the new task from queue and execute it. Since the new task is now the only task in the scheduler, it could be run without creating a new Thread.

要解决此问题,您可以编译

To solve this problem, you can combile @Async and @Scheduled

SchedulerConfig

SchedulerConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {
    private final int POOL_SIZE = 10;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setTaskScheduler(poolScheduler());
    }

    @Bean
    public TaskScheduler poolScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("poolScheduler");
        scheduler.setPoolSize(POOL_SIZE);
        return scheduler;
    }

}

SchedulerTask

SchedulerTask

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

@Component
public class SchedulerTask {

    @Autowired
    private AsyncTask asyncTask;

    @Scheduled(fixedRateString = "2000" )
    public void testaMethod() {
        asyncTask.asyncMethod();
    }
}

AsyncTask

AsyncTask

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

@Component
@EnableAsync
public class AsyncTask {

    private Log log = LogFactory.getLog(AsyncTask.class);

    @Async
    public void asyncMethod() {
        log.debug("here is the message");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试结果

11:20:54.682 [poolScheduler1] DEBUG com.test.AsyncTask - here is the message
11:20:56.668 [poolScheduler3] DEBUG com.test.AsyncTask - here is the message
11:20:58.668 [poolScheduler2] DEBUG com.test.AsyncTask - here is the message
11:21:00.669 [poolScheduler6] DEBUG com.test.AsyncTask - here is the message
11:21:02.669 [poolScheduler7] DEBUG com.test.AsyncTask - here is the message
11:21:04.669 [poolScheduler4] DEBUG com.test.AsyncTask - here is the message

这篇关于spring-boot @scheduled无法在其他线程中运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆