Is it safe for my Java (Tomcat 8) web server to spawn threads in response to a HTTP request? I\'m seeing posts and forums where some people say it\'s absolutely fine, and ot
First, it looks you're modifying the result object in both threads. This is not thread safe because what the first and second threads do might not be visible to each other or to the thread the servlet is running on. See this article for more info.
Second, if you are modifying the response in these other threads, no, this will not be safe. Once you exit the doGet method, you should consider the response sent. In your example, there's a chance the response will get sent back to the client before those two threads have run.
Suppose the MyResult result affects the response object (you're either adding the result to the response, it's affecting the response code, etc). There are a few ways to handle this.
Use ExecutorService and Future:
public void doGet(HttpServletRequest request, HttpServletResponse response) {
// Creating a new ExecutorService for illustrative purposes.
// As mentioned in comments, it is better to create a global
// instance of ExecutorService and use it in all servlets.
ExecutorService executor = Executors.newFixedThreadPool(2);
Future f1 = executor.submit(new Callable() {
@Override
public Result1 call() throws Exception {
// do expensive stuff here.
return result;
}
});
Future f2 = executor.submit(new Callable() {
@Override
public Result2 call() throws Exception {
// do expensive stuff here.
return result;
}
});
// shutdown allows the executor to clean up its threads.
// Also prevents more Callables/Runnables from being submitted.
executor.shutdown();
// The call to .get() will block until the executor has
// completed executing the Callable.
Result1 r1 = f1.get();
Result2 r2 = f2.get();
MyResult result = new MyResult();
// add r1 and r2 to result.
// modify response based on result
}
A more advanced technique is Asynchronous Processing. Using async processing is a good idea if your requests take a long time to process. It does not improve the latency of any one request, but it does allow Tomcat to handle more requests at any given point in time.
A simple example would be:
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
// Rather than @WebServlet, you can also specify these parameters in web.xml
public class AsyncServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("text/html;charset=UTF-8");
final AsyncContext acontext = request.startAsync();
acontext.start(new Runnable() {
public void run() {
// perform time consuming steps here.
acontext.complete();
}
}