2017-08-22 131 views
0

在spring boot 1.5.4上使用jhipster,我很難獲得異步執行的後臺任務;它們似乎是使用與我配置的不同taskExecutor和線程池同步運行的。Java Spring異步執行

所有這一切都發生在一個服務,這對於bevity,就像這樣定義:

@Service 
@Transactional 
public class AppService { 
    @Scheduled(fixedDelay = 3000) 
    public void consumeData() { 
     // connect to a subscriber and push data to the workerBee 
     for(Tuple data : this.getTuples()) { 
      workerBee(data); 
     } 
    } 

    @Timed 
    @Async 
    public void workerBee(Tuple data) throws Exception { 
     // ... do something that takes 300ms .... 
     Thread.sleep(300); 
    } 
} 

可以說,服務是不是對這項工作的理想場所,但出於演示的目的,它適合。

(也順便說一句,它apears @Timed不工作,但我讀的地方,@Timed不工作時,在服務中內部調用)

application.yml有關章節:

jhipster: 
    async: 
     core-pool-size: 8 
     max-pool-size: 64 
     queue-capacity: 10000 

使用缺省值生成AsyncConfiguration.java,它看起來像這樣:

@Override 
@Bean(name = "taskExecutor") 
public Executor getAsyncExecutor() { 
    log.debug("Creating Async Task Executor"); 
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
    executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize()); 
    executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize()); 
    executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity()); 
    executor.setThreadNamePrefix("app-Executor-"); 
    return new ExceptionHandlingAsyncTaskExecutor(executor); 
} 

我已經驗證了taskExecutor豆是越來越創建正在被liquibase使用。

當我連接visualvm時,我看到所有在pool-2-thread-1中發生的工作,這些工作肯定是某種默認的,很明顯,工作是同步發生的,而不是異步的。

事情我已經嘗試:

  • 指定遺囑執行人在@Async註釋像@Async("taskExecutor")
  • 驗證了taskExecutor的配置與核心池大小的8個線程。
  • 驗證應用程序是否具有@EnableAsync註釋(默認情況下爲它)。

回答

0

一種替代方法是改變@Bean getAsyncExecutor這樣:

@Bean 
public ThreadPoolTaskExecutor threadPoolTaskExecutor() { 
    log.debug("Creating Async Task Executor"); 
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
    executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize()); 
    executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize()); 
    executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity()); 
    executor.setThreadNamePrefix("app-Executor-"); 
    return executor; 
} 
+0

我沒有看到你在這裏做除了去掉ExceptionHandlingAsyncTaskExecutor包裝輪執行什麼。爲什麼會/應該有幫助? –

+0

忽略答案我只知道你正在使用jhipster –

0

備選方案2:調用使用CompletableFuture

在這裏,在同一類中的異步方法是另一種方法,如果您需要使用異步方法並使用CompletableFuture在同一類中調用並注入從AsyncConfiguration生成的Executor

@Service 
public class MyAsyncProcess { 

    private final Logger log = LoggerFactory.getLogger(MyAsyncProcess.class); 

    @Autowired 
    Executor executor; 


    @Scheduled(cron = "*/8 * * * * *") 
    public void consumeData() { 

     IntStream.range(0,20).forEach((s) -> 
      CompletableFuture.supplyAsync(() -> { return workerBeeCompletableFuture(String.valueOf(s)); } , executor)); 
    } 


    public CompletableFuture<String> workerBeeCompletableFuture(String data) { 

     log.debug("workerBeeCompletableFuture: Iteration number: " + data + " Thread: " + Thread.currentThread().getName()); 

     try { Thread.sleep(2000); } 
     catch (InterruptedException e) { e.printStackTrace(); } 

     return CompletableFuture.completedFuture("finished"); 

    } 

替代1使用@Async

我終於是什麼原因造成這種現象,其實​​呼籲到workerBee作爲本地方法,而不是作爲@Async方法。

爲了使@Async工作剛剛創建的@ScheduleMySchedulerService@AutowiredAppService@ServiceMySchedulerService。從AppService類中刪除@Schedule

它應該是這樣的:

@Service 
public class MyAsyncProcess { 

    private final Logger log = LoggerFactory.getLogger(MyAsyncProcess.class); 

    @Async 
    public void workerBeeAsync(String data) { 
     // ... do something that takes 300ms .... 
     try { 
      log.debug("Iteration number: " + data + " Thread: " + Thread.currentThread().getName()); 

      Thread.sleep(2000); 
      log.debug("finished"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

和日程表服務

@Service 
public class MySchedule { 

    @Autowired 
    MyAsyncProcess myAsyncProcess; 

    @Scheduled(cron = "*/8 * * * * *") 
    public void consumeData() { 

     IntStream.range(0,20).forEach(s -> 
      myAsyncProcess.workerBeeAsync(String.valueOf(s))); 

    } 

} 

application.yml我使用以下值:

jhipster: 
    async: 
     core-pool-size: 50 
     max-pool-size: 100 
     queue-capacity: 10000 

@Async會自動檢測Executor配置在AsyncConfigurer類。

希望它能幫助你。

1

看起來我不遵循這裏列出的規則:http://www.baeldung.com/spring-async。最值得注意的是自我調用:

@Async有兩個限制:

it must be applied to public methods only 
self-invocation – calling the async method from within the same class – won’t work 
+0

是的你的結論是正確的! –