在@Scheduled方法中调用Spring @Async方法

Sou*_*aik 7 java spring spring-boot spring-async

我正在使用Spring启动@EnableScheduling@EnableAsync.

我有一个注释的方法@Scheduled.我有几个方法,用注释@Async.

现在我在@Async方法中调用这些方法,@Scheduled并在异步方法中打印出当前线程的名称.我看到的是它们都有相同的线程名称,实际上它是运行该@Scheduled方法的线程.

我没有看到异步方法执行.这有什么不对?

这是我的应用程序启动类

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class ApplicationBoot {

    public static void main(String[] args) {
        SpringApplication.run(ApplicationBoot.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的调度程序类

@Component
public class TaskScheduler {
    private static final Logger logger = Logger.getLogger(TaskScheduler.class);

    @Scheduled(fixedDelay = 10000)
    public void ScheduledMethod() {
        methodOne();
        methodTwo();
        methodThree();
    }

    @Async
    private void methodOne() {
        logger.info("Method one called  by Thread : " + Thread.currentThread().getName() + "  at " + new Date());
    }

    @Async
    private void methodTwo() {
        logger.info("Method two called  by Thread : " + Thread.currentThread().getName() + "  at " + new Date());
    }

    @Async
    private void methodThree() {
        logger.info("Method three called  by Thread : " + Thread.currentThread().getName() + "  at " + new Date());
    }
}
Run Code Online (Sandbox Code Playgroud)

产量

方法一由Thread调用:pool-1-thread-1在Tue Apr 04 16:32:27 IST 2017

方法二由Thread调用:pool-1-thread-1在Tue Apr 04 16:32:27 IST 2017

方法三由Thread调用:pool-1-thread-1在Tue Apr 04 16:32:27 IST 2017

Nic*_*rot 11

说明

Spring会在您的实例周围创建代理.ScheduledMethod内部调用3个方法,这些方法未被代理,因此不是异步的.

比照 文件:

如果在对象引用上调用方法,则直接在该对象引用上调用该方法,如下所示.

看到这个问题Spring AOP无法正常工作,当在bean内部调用该方法 以获得解决方法时,最好是在doc中提出的方法The best approach (the term best is used loosely here) is to refactor your code such that the self-invocation does not happen...

请注意,也不支持私有方法:

由于Spring的AOP框架基于代理的特性,受保护的方法根据定义不会被拦截,既不用于JDK代理(这不适用),也不用于CGLIB代理(这在技术上可行,但不建议用于AOP).因此,任何给定的切入点都只能与公共方法匹配!

解决方法示例

@Component
public class ServiceMethod {
    private static final Logger logger = Logger.getLogger(ServiceMethod .class);

    @Async
    public void methodOne() {
        logger.info("Method one called  by Thread : " + Thread.currentThread().getName() + "  at " + new Date());
    }

    @Async
    public void methodTwo() {
        logger.info("Method two called  by Thread : " + Thread.currentThread().getName() + "  at " + new Date());
    }

    @Async
    public void methodThree() {
        logger.info("Method three called  by Thread : " + Thread.currentThread().getName() + "  at " + new Date());
    }
}

@Component
public class TaskScheduler {
    private static final Logger logger = Logger.getLogger(TaskScheduler.class);

    @Autowired
    private ServiceMethod serviceMethod;

    @Scheduled(fixedDelay = 10000)
    public void ScheduledMethod() {
        serviceMethod.methodOne();
        serviceMethod.methodTwo();
        serviceMethod.methodThree();
    }
}
Run Code Online (Sandbox Code Playgroud)


Abd*_*han 5

你可能还没有配置Thread Pool更多的ThreadsScheduler

文档

如果不提供 pool-size 属性,则默认线程池将只有一个线程。