Ich versuche, die XML-Konfiguration für die Verwendung des Spring-Aufgaben-Frameworks in eine reine Code-Konfiguration zu konvertieren. Ich bin in der Lage, die Funktionalität zu reproduzieren, aber jedes Mal, wenn ich den Krieg auf dem Tomcat-Server herunterfahre, auf dem der Task-Scheduler läuft, bleibt er hängen (er hängt nicht mit der XML-Konfiguration). Ich habe getestet, um die Instanzen von Scheduler und Executor zu überprüfen, aber ich sehe keinen Unterschied, so dass ich nicht sicher bin, was es verursachen könnte. HierUmwandlung der Spring-Task-XML-Konfiguration in Code-Konfiguration
ist die XML-Konfiguration, die funktioniert:
<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>
Hier ist der Code-Konfiguration:
@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();
}
}
Wenn ich setExecuteExistingDelayedTasksAfterShutdownPolicy(false)
in Code-Konfiguration verwenden, wird es heruntergefahren, aber ich mache mir Sorgen, dass Macht nachteilige Auswirkungen haben, wenn dies über die XML-Konfiguration geschieht. Außerdem sollte ich anmerken, dass die QueueProcessor-Klasse die Arbeit macht, die ich möchte, und es macht mir nichts aus, wenn verzögerte Ausführungen abgebrochen werden - ich möchte gerade nicht, dass die Ausführung von Threads abrupt abgebrochen wird.
Dies ist die Botschaft, die ich erhalten, wenn es hängt:
SCHWEREN: Die Web-Anwendung [/ pix-Queue-Prozessor] begann einen Thread namens [ThreadPoolTaskExecutor-1] aber hat es versäumt zu haben scheint Hör auf. Dies führt sehr wahrscheinlich zu einem Speicherleck.
Irgendwelche Ideen auf, was das Hängen verursachen könnte? Oder würde ich mit dieser auskommentierten Methode tun, was ich will (wird eine laufende Aufgabe nicht töten, aber verzögerte Aufgaben abbrechen)?
Eines der Probleme, die ich sehe, ist dass Sie einen neuen 'ThreadPoolTaskExecutor 'als' ThreadFactory' setzen? Warum? Sie haben jetzt im Grunde zwei Task Executors, von denen einer kontrolliert wird und der andere nicht wirklich. –
Ein anderer Grund ist, warum Sie Ihren 'TaskExecutor' nicht an Ihren 'TaskScheduler'? Das verwendet einen weiteren nicht verwalteten' TaskExecutor'. –