Wednesday, December 12, 2012

Can I spawn a background thread from my servlet?


You are allowed to spawn a thread from a Servlet. Sounds like you want to make a thread object and store it as an attribute in your application context. See the FAQ I want the servlet container to load one or more servlets when the container is first fired up, as opposed to when a client issues a request for the servlets for how to start it. Basically, you make a thread object, call mythread.start(), then call context.setAttribute("mythread", mythread).
You can give your daemon object methods to activate and deactivate, but it will be accessible (almost a global) from any servlet at any time.
This can be used to run, e.g., a chat server that accepts socket connections from an applet, independently of the Web server (and on a different port than 80 or 8080). Or a status-checker that performs some action periodically, like updating a cache or monitoring a database connection.
Here's some simple (untested) code that spawns a daemon thread that keeps track of the number of seconds since it's been launched.
public class DaemonStarter extends HttpServlet {
 public void init() {
  TimerDaemon d = new TimerDaemon();
  d.start();
  getServletContext().setAttribute("daemon", d);
 }
}

public class MyDaemon extends Thread {
 long secs = 0;
 public void run() {
  while (true) {
   Thread.sleep(1000);
   secs++;
  }
 }
 public long getSecs() {
  return secs;
 }
}

public class PrintSecs extends HttpServlet {
 public class doGet(...) {
  TimerDaemon d = (TimerDaemon)getServletContext().getAttribute("daemon");
  response.getWriter().println( d.getSecs() );
 }
}
Note that this can be dangerous in a load-balanced application, as when using the "distributed" flag in your web.xml. You must be aware if your background thread will be running in multiple VMs, and if that will cause any sychronization problems.

No comments:

Post a Comment