2017-04-04 76 views
3

我使用Spring的引导与@EnableScheduling@EnableAsync春@Async方法调用内部@Scheduled方法

我具有被注解为@Scheduled的方法。 我有几个方法,这些方法都标注了@Async

现在我在@Scheduled方法中调用这些@Async方法,并在异步方法中打印出当前线程的名称。我看到的是他们都有同一个线程的名字,这实际上是运行@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()); 
    } 
} 

输出

方法一通过线程调用:池1线程-1星期二4月4日16时32分27秒IST 2017年

方法二由线程调用:pool-1-thread-1 at 4 Apr 04 16:32:27 IST 2017

方法三由Thread调用:pool-1-thread-1 at Apr 4 04:32:27 IST 2017

+3

一些代码示例将是有益的。 – Manuel

+1

除了代码请后配置和示例输出表现出所述行为 –

+0

@Manuel加入样本代码。 –

回答

3

您可能尚未为您的Scheduler配置Thread Pool以及更多Threads

docs

如果你不提供一个游泳池大小的属性,默认的线程池只会有一个线程。

8

说明

春天围绕创建您的实例的代理。 ScheduledMethod在内部调用3个方法,这些方法不被代理,因此也不是异步的。

cf. the documentation

如果调用上的对象的参考的方法,该方法是直接调用 对对象的引用,如在下面可以看到。

看到这个问题Spring AOP not working, when the method is called internally within a 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...

注意的一个,私有方法是不supported too

由于基于代理的Spring的AOP框架的性质,保护 方法是通过定义不拦截,既不是JDK代理 (其中,这是不适用),也不是CGLIB代理(如使用 TECHN对于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(); 
    } 
}