Java ExecutorService顺序-Spring MVC
Java ExecutorService sequentially -Spring MVC
我想在我的 Spring-MVC 应用程序中实现 ExecutorService。
我需要一个全局的 ExecutorService,它将任务放入一个队列中,然后按顺序执行它们。所以我想从应用程序的不同位置传递任务。因此我使用 Executors.newSingleThreadExecutor();
所以我只有 1 个线程执行这些任务。
但是,我不确定如何将它集成到 Spring 应用程序中:
public enum TaskQueue {
INSTANCE;
ExecutorService executorService;
private TaskQueue() {
executorService = Executors.newSingleThreadExecutor();
}
public void addTaskToQueue (Runnable task){
executorService.submit(task);
executorService.shutdown();
}
}
所以我正在考虑创建一个 Singleton,然后将 Task(Runnable 对象)传递给方法:
TaskQueue.INSTANCE.addTaskToQueue(new Runnable() {
@Override
public void run() {
System.out.println("Executing Task1 inside : " + Thread.currentThread().getName());
}
});
但是,我有几个问题:
我不确定如何将它集成到我有控制器、服务等的 Spring MVC 应用程序中。
应用程序从网络服务接收一些通知。这些通知将在代码中的不同位置进行处理。我想要
依次执行它们。所以我需要异步识别我想要 运行 的所有任务,然后将它们传递给包装在 Runnabel 对象中的上述方法 (`addTaskToQueue),这样它们就可以异步执行。这是正确的方法吗?
所以我总是传递一个Runnable对象给这个方法来执行它。此方法执行它并关闭 executorservice。因此,每次我将任务传递给该服务时,它都会创建一个新服务,然后将其关闭。但我不想那样做——我希望 executorservice 保持活动状态并执行即将到来的任务,而不是在每个任务后关闭。我该如何实现?
或者我以这种方式实现它是完全错误的吗?
编辑:
使用 Spring 提供的 TaskExecutor - 我会这样实现它:
@Autowired
private TaskExecutor taskExecutor;
然后在我的代码中从不同的位置调用它:
taskExecutor.execute(new Runnable() {
@Override
public void run() {
//TODO add long running task
}
});
可能我需要确保配置中的某处需要按顺序执行 - 所以它应该只创建 1 个线程。从不同的地方调用它安全吗?它不会总是使用新队列创建新服务吗?
Spring 已经有一个用于此的 bean:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
。它实现 DisposableBean
接口,当 Spring 上下文被销毁时调用 shutdown()
方法。
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${threadPoolSize}"/>
<property name="maxPoolSize" value="${threadPoolSize}"/>
<property name="WaitForTasksToCompleteOnShutdown" value="false"/>
</bean>
Singleton 设计模式不太适合这种情况。由于您使用的是 Spring,因此使用 @PostConstruct
和 @PreDestroy
方法制作组件更有意义。 Here and here 是对此进行解释的文章。
对于您的情况,我会执行以下操作:
@Component
public class TaskQueue {
private ExecutorService executorService;
@PostConstruct
public void init() {
executorService = Executors.newSingleThreadExecutor();
}
@PreDestroy
public void cleanup() {
executorService.shutdown();
}
public void addTaskToQueue (Runnable task){
executorService.submit(task);
}
}
然后你就可以自动装配这个组件了。
编辑:@Ivan 的回答是首选。
我想在我的 Spring-MVC 应用程序中实现 ExecutorService。
我需要一个全局的 ExecutorService,它将任务放入一个队列中,然后按顺序执行它们。所以我想从应用程序的不同位置传递任务。因此我使用 Executors.newSingleThreadExecutor();
所以我只有 1 个线程执行这些任务。
但是,我不确定如何将它集成到 Spring 应用程序中:
public enum TaskQueue {
INSTANCE;
ExecutorService executorService;
private TaskQueue() {
executorService = Executors.newSingleThreadExecutor();
}
public void addTaskToQueue (Runnable task){
executorService.submit(task);
executorService.shutdown();
}
}
所以我正在考虑创建一个 Singleton,然后将 Task(Runnable 对象)传递给方法:
TaskQueue.INSTANCE.addTaskToQueue(new Runnable() {
@Override
public void run() {
System.out.println("Executing Task1 inside : " + Thread.currentThread().getName());
}
});
但是,我有几个问题:
我不确定如何将它集成到我有控制器、服务等的 Spring MVC 应用程序中。
应用程序从网络服务接收一些通知。这些通知将在代码中的不同位置进行处理。我想要 依次执行它们。所以我需要异步识别我想要 运行 的所有任务,然后将它们传递给包装在 Runnabel 对象中的上述方法 (`addTaskToQueue),这样它们就可以异步执行。这是正确的方法吗?
所以我总是传递一个Runnable对象给这个方法来执行它。此方法执行它并关闭 executorservice。因此,每次我将任务传递给该服务时,它都会创建一个新服务,然后将其关闭。但我不想那样做——我希望 executorservice 保持活动状态并执行即将到来的任务,而不是在每个任务后关闭。我该如何实现?
或者我以这种方式实现它是完全错误的吗?
编辑:
使用 Spring 提供的 TaskExecutor - 我会这样实现它:
@Autowired
private TaskExecutor taskExecutor;
然后在我的代码中从不同的位置调用它:
taskExecutor.execute(new Runnable() {
@Override
public void run() {
//TODO add long running task
}
});
可能我需要确保配置中的某处需要按顺序执行 - 所以它应该只创建 1 个线程。从不同的地方调用它安全吗?它不会总是使用新队列创建新服务吗?
Spring 已经有一个用于此的 bean:org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
。它实现 DisposableBean
接口,当 Spring 上下文被销毁时调用 shutdown()
方法。
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${threadPoolSize}"/>
<property name="maxPoolSize" value="${threadPoolSize}"/>
<property name="WaitForTasksToCompleteOnShutdown" value="false"/>
</bean>
Singleton 设计模式不太适合这种情况。由于您使用的是 Spring,因此使用 @PostConstruct
和 @PreDestroy
方法制作组件更有意义。 Here and here 是对此进行解释的文章。
对于您的情况,我会执行以下操作:
@Component
public class TaskQueue {
private ExecutorService executorService;
@PostConstruct
public void init() {
executorService = Executors.newSingleThreadExecutor();
}
@PreDestroy
public void cleanup() {
executorService.shutdown();
}
public void addTaskToQueue (Runnable task){
executorService.submit(task);
}
}
然后你就可以自动装配这个组件了。
编辑:@Ivan 的回答是首选。