Probably a repeat! I am using Tomcat as my server and want to know what is best way to spawn threads in the servlet with deterministic outcomes. I am running some long running updates from a servlet action and would like for the request to complete and the updates to happen in the background. Instead of adding a messaging middleware like RabbitMQ, I thought I could spawn a thread that could run in the background and finish in its own time. I read in other SO threads that the server terminates threads spawned by the server in order for it to manage resources well.
Is there a recommended way of spawning threads, background jobs when using Tomcat. I also use Spring MVC for the application.
By default, Tomcat sets maxThreads to 200, which represents the maximum number of threads allowed to run at any given time. You can also specify values for the following parameters: minSpareThreads : the minimum number of threads that should be running at all times.
Each request is handled in a different thread. This is not a "thread per user". A request is any interaction from the client (web browser) and the server.
The Apache Tomcat's threadpool (is it called the connector Threadpool? ) has a number of threads ( 200 by default ). Now this means that at a particular time, 200 people can communicate with my web application. Now, taking a scenario when a particular connects with my application.
Tomcat will invoke your code (i.e. your servlets) from multiple threads, and if that code is not thread-safe, you'll have problems. Tomcat's threads are no different to any threads you create yourself.
In a barebones servletcontainer like Tomcat or Jetty, your safest bet is using an applicaton wide thread pool with a max amount of threads, so that the tasks will be queued whenever necessary. The ExecutorService
is very helpful in this.
Upon application startup or servlet initialization use the Executors
class to create one:
executor = Executors.newFixedThreadPool(10); // Max 10 threads.
Then during servlet's service (you could ignore the result for the case that you aren't interested, or store it in the session for later access):
Future<ReturnType> result = executor.submit(new YourTask(yourData));
Where YourTask
must implement Runnable
or Callable
and can look something like this, whereby yourData
is just your data, e.g. populated with request parameter values (just keep in mind that you should absolutely not pass Servlet API artifacts such as HttpServletRequest
or HttpServletResponse
along!):
public class YourTask implements Runnable { private YourData yourData; public YourTask(YourData yourData) { this.yourData = yourData; } @Override public void run() { // Do your task here based on your data. } }
Finally, during application's shutdown or servlet's destroy you need to explicitly shutdown it, else the threads may run forever and prevent the server from properly shutting down.
executor.shutdownNow(); // Returns list of undone tasks, for the case that.
In case you're actually using a normal JEE server such as WildFly, Payara, TomEE, etc, where EJB is normally available, then you can simply put @Asynchronous
annotation on an EJB method which you invoke from the servlet. You can optionally let it return a Future<T>
with AsyncResult<T>
as concrete value.
@Asynchronous public Future<ReturnType> submit() { // ... Do your job here. return new AsyncResult<ReturnType>(result); }
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