2015-05-13 47 views
11

我試圖將使用Spring的任務框架的XML配置轉換爲純代碼配置。我能夠重現這些功能,但每當我關閉任務調度程序所在的Tomcat服務器上的戰爭時,它就會掛起(它不會與XML配置掛起)。我已經調試過檢查調度程序和執行程序的實例,但是我沒有看到區別,所以我不確定可能導致它掛起的原因。將Spring任務XML配置轉換爲代碼配置

下面是XML配置的作品:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd"> 

    <task:executor id="com.work.gwx.pix.executor" 
     pool-size="${pix.job.executor.pool.size:1-40}" 
     queue-capacity="${pix.job.executor.queue.capacity:0}" 
     rejection-policy="CALLER_RUNS"/> 

    <task:scheduler id="com.work.gwx.pix.scheduler" pool-size="${pix.job.scheduler.pool.size:4}" /> 

    <task:annotation-driven executor="com.work.gwx.pix.executor" scheduler="com.work.gwx.pix.scheduler" /> 

    <bean id='queueProcessor' class="com.work.gwx.queueing.QueueProcessor" /> 

</beans> 

下面是代碼的配置:

@EnableAsync 
@EnableScheduling 
@Configuration 
public class TaskConfiguration implements AsyncConfigurer, SchedulingConfigurer { 

    @Value("${pix.job.executor.max.pool.size:1}") 
    private int executorMaxPoolSize; 

    @Value("${pix.job.executor.queue.capacity:0}") 
    private int executorQueueCapacity; 

    @Value("${pix.job.scheduler.pool.size:4}") 
    private int schedulerPoolSize; 

    @Bean(destroyMethod = "shutdown") 
    public Executor pixTaskScheduler() { 
     final ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(schedulerPoolSize, new ThreadPoolTaskExecutor()); 
     // ex.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); 
     return ex; 
    } 

    @Bean 
    public Executor pixExecutor() { 
     final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
     executor.setCorePoolSize(executorMaxPoolSize); 
     executor.setQueueCapacity(executorQueueCapacity); 
     executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
     executor.setThreadFactory(new ThreadPoolTaskExecutor()); 
     executor.initialize(); 
     return executor; 
    } 

    @Override 
    public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) { 
     taskRegistrar.setScheduler(pixTaskScheduler()); 

    } 

    @Override 
    public Executor getAsyncExecutor() { 
     return pixExecutor(); 
    } 

    @Override 
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 
     return new SimpleAsyncUncaughtExceptionHandler(); 
    } 
} 

當我使用代碼配置setExecuteExistingDelayedTasksAfterShutdownPolicy(false)它關閉,但我擔心這可能如果通過XML配置完成設置爲true,則會產生不利影響。另外,我應該注意到,QueueProcessor類正在做我想要的工作,我不介意延遲執行會被取消 - 我只是不希望當前正在執行的線程被突然取消。

這是我得到的,當它掛起消息:

重度:Web應用程序[/ PIX-隊列處理器]似乎有 開了一家名叫[ThreadPoolTask​​Executor類-1]線程,但未能 停止它。這很可能造成內存泄漏。

任何想法可能會導致掛?或者,使用那個註釋掉的方法讓我做我想做的事(不會殺死正在運行的任務,但會取消延遲的任務)?

+0

一個我看到的是問題你爲ThreadFactory設置了一個新的'ThreadPoolTask​​Executor'爲什麼?你現在基本上有兩個任務執行器,其中一個是受控的,另一個不是真的。 –

+0

另一件事是爲什麼你不把你的'TaskExecutor'連接到你的'TaskScheduler'?這是使用另一個非託管的'TaskExecutor'。 –

回答

4

您的基於Java的配置實際上不是XML配置的表示。至少有兩件事情是不同的。

  1. TaskExecutor有另一個TaskExecutor有線作爲ThreadFactory這不是XML的情況下,也開始另一TaskExecutor
  2. 您的TaskScheduler使用新的TaskExecutor而xml配置使用配置的配置。

在有你的任務完成了關機,你可以在TaskExecutorwaitForTasksToCompleteOnShutdown屬性設置爲true那麼任何尚未完成的任務將完成,並沒有新的任務將被接受。

此外,initialize也不需要調用,因爲afterPropertiesSet方法將被Spring調用,該方法將調用initialize

以下2個bean定義都更加符合XML配置行(你現在有一個TaskExecutor,而不是3,它會先關閉之前完成任務。

@Bean(destroyMethod = "shutdown") 
public Executor pixTaskScheduler() { 
    final ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(schedulerPoolSize, pixExecutor()); 
    // ex.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); 
    return ex; 
} 

@Bean 
public Executor pixExecutor() { 
    final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
    executor.setCorePoolSize(executorMaxPoolSize); 
    executor.setQueueCapacity(executorQueueCapacity); 
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
    executor.setWaitForTasksToCompleteOnShutdown(true); 
    return executor; 
} 
+0

對不起,我還沒有迴應,因爲我不在城裏。看起來很有前途,應該能夠很快測試出來。這是有道理的你在說什麼。 – AHungerArtist

+0

這似乎有效,但還有一個問題:在XML中,我可以爲執行者和調度程序提供名稱/標識。我怎麼能通過代碼來做到這一點? ThreadPoolTask​​Executor似乎有一個方法,但不是預定的方法。這將有助於確定在調試時哪些線程來自此。 – AHungerArtist

+0

不,它不會因爲只有一個線程池。對於'ThreadPoolTask​​Executor',你可以使用'threadNamePrefix'來添加一個前綴。但是調度器只是一個使用單個ThreadPoolTask​​Executor來啓動任務的調度器。如果你不希望你需要添加另一個任務執行程序,但這不是你在xml配置中擁有(或已經)的。 –