8

我正在使用 Spring Boot@EnableScheduling@EnableAsync.

我有一个用@Scheduled. 我还有一些方法,用@Async.

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

我没有看到异步方法执行。这里有什么问题?

这是我的应用程序启动类

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class ApplicationBoot {

    public static void main(String[] args) {
        SpringApplication.run(ApplicationBoot.class, args);
    }
}

这是我的调度程序类

@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());
    }
}

输出

线程调用的方法一:pool-1-thread-1 于 2017 年 4 月 4 日星期二 16:32:27 IST

线程调用的方法二:2017 年 4 月 4 日星期二 16:32:27 的 pool-1-thread-1

线程调用的方法三:2017 年 4 月 4 日星期二 16:32:27 的 pool-1-thread-1

4

2 回答 2

13

解释

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

参看。文档

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

看到这个问题Spring AOP not working, when the method is called internal within a bean for a workaround,但最好的是文档中提出的那个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();
    }
}
于 2017-04-04T11:22:03.117 回答
5

您可能没有Thread PoolThreads您的Scheduler.

文档

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

于 2017-04-04T10:47:42.073 回答