I have ThreadPoolTaskExecutor. I should send too many emails (different emails). If I have error during email sending, I should write it in database.
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>
I'm executing tasks. taskExecutor.execute(Runable). Everything works well!
@Override
public void run() {
try {
mailService.sendMail();
} catch (Throwable t) {
daoService.writeFaillStatus();
}
}
Everything seems ok! Async request are doing well!
I also have
white(true) {
if(executor.getActiveCount()==0){
executor.shutdown(); break;
}
Thread.sleep(3000)
}
Because of WaitForTasksToCompleteOnShutdown=true task never will be shut down automatically. In the other words, main thread never will be destroyed (Main thread is the thread where I invoke thread executor tasks - when I run code in eclipse, terminal is active always). Even after executor thread will finish their work my console looks like this:
I think this is because, main thread is waiting something - someone who tell that "everything is already done, relax, go and shut down"
So thought about this solution while(true). Could you tell me if this is good idea? Might be it is not good.
I know that this executor also have submit() method. I think I do not need here. Please correct me If I am not correct in this post.
Because you are using the Spring ThreadPoolTaskExecutor
, you are in luck.
If you configure the following it will allow you specify a number of seconds to wait before forcing a shutdown.
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="WaitForTasksToCompleteOnShutdown" value="true" />
<property name="awaitTerminationSeconds" value="X" />
</bean>
Set the value of X to be however many seconds you want the process to wait before terminating.
From the documentation for awaitTerminationSeconds
If the "waitForTasksToCompleteOnShutdown" flag has been set to true, it will continue to fully execute all ongoing tasks as well as all remaining tasks in the queue, in parallel to the rest of the container shutting down. In either case, if you specify an await-termination period using this property, this executor will wait for the given time (max) for the termination of tasks. As a rule of thumb, specify a significantly higher timeout here if you set "waitForTasksToCompleteOnShutdown" to true at the same time, since all remaining tasks in the queue will still get executed - in contrast to the default shutdown behavior where it's just about waiting for currently executing tasks that aren't reacting to thread interruption.
Basically, you are trying to forcefully do something that should be solely handled by the framework. It should be the framework that decides when to shut down the task executor, due to exceptional circumstances. I would remove all your code that is trying to shut down the task executor, and let Spring handle that shut down, when all your jobs have finished. Then Spring will properly shut down the main as well.
If you know before hand how many are "too many emails", I would suggest to take a look at CountDownLatch
rather than the busy wait loop to check the task status.
In main thread set the
CountDownLatch latch = new CountDownLatch(TOO_MANY_EMAILS);
Pass this instance to runnable instance, where we call latch.countDown()
after sending each mail.
In the main thread we wait for the latch to countdown: latch.await()
. This will block main thread execution.
After which you could safely shutdown the thread pool knowing all the work has been completed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With