Está mezclando diferentes conceptos. Debe distinguir entre:
- asíncrono solicitud de entrega de acuerdo con Servlet 3.0; una API que le permite desacoplar una solicitud de servlet entrante del grupo de subprocesos de contenedor web. No crea ningún hilo sobre la marcha. El usuario de la interfaz debe implementar una solución de múltiples subprocesos adecuada. No se relaciona con IO sin bloqueo.
- Grupo de subprocesos; proporciona un mecanismo para obtener y administrar hilos en un contenedor web. Cuando se trata de solicitud asincrónica entregando tiene 2 opciones. Puede definir su propio
ExecutorService
y usarlo para seguir procesando la solicitud o puede crear un nuevo Runnable
y enviarlo al AsyncContext
obtenido llamando al AsyncContext.start()
. En el caso de Tomcat, el último enfoque utiliza el grupo de subprocesos de Tomcat definido en server.xml
.
- IO sin bloqueo (NIO); Aunque es asincrónico también es una historia diferente. Se refiere a operaciones IO sin bloqueo, como disco o red IO. Si desea habilitar NIO para el procesamiento de solicitud HTTP, eche un vistazo a Tomcat's documentation.
El ejemplo a continuación describe cómo se puede trabajo. Utiliza solo un hilo para trabajos de trabajadores. Si se ejecuta desde 2 navegadores diferentes en paralelo la salida tiene este aspecto (utilizo un registrador de encargo):
DATE THREAD_ID LEVEL MESSAGE
2011-09-03 11:51:22.198 +0200 26 I: >doGet: chrome
2011-09-03 11:51:22.204 +0200 26 I: <doGet: chrome
2011-09-03 11:51:22.204 +0200 28 I: >run: chrome
2011-09-03 11:51:27.908 +0200 29 I: >doGet: firefox
2011-09-03 11:51:27.908 +0200 29 I: <doGet: firefox
2011-09-03 11:51:32.227 +0200 28 I: <run: chrome
2011-09-03 11:51:32.228 +0200 28 I: >run: firefox
2011-09-03 11:51:42.244 +0200 28 I: <run: firefox
Usted ve que los métodos doGet
terminan inmediatamente, mientras que el trabajador todavía funciona. Las 2 solicitudes de prueba: http://localhost:8080/pc/TestServlet?name=chrome
y http://localhost:8080/pc/TestServlet?name=firefox
.
ejemplo simple servlet
@WebServlet(asyncSupported = true, value = "/TestServlet", loadOnStartup = 1)
public class TestServlet extends HttpServlet {
private static final Logger LOG = Logger.getLogger(TestServlet.class.getName());
private static final long serialVersionUID = 1L;
private static final int NUM_WORKER_THREADS = 1;
private ExecutorService executor = null;
@Override
public void init() throws ServletException {
this.executor = Executors.newFixedThreadPool(NUM_WORKER_THREADS);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String name = request.getParameter("name");
LOG.info(">doGet: " + name);
AsyncContext ac = request.startAsync(); // obtain async context
ac.setTimeout(0); // test only, no timeout
/* Create a worker */
Runnable worker = new TestWorker(name, ac);
/* use your own executor service to execute a worker thread (TestWorker) */
this.executorService.execute(worker);
/* OR delegate to the container */
// ac.start(worker);
LOG.info("<doGet: " + name);
}
}
... y el TestWorker
public class TestWorker implements Runnable {
private static final Logger LOG = Logger.getLogger(TestWorker.class.getName());
private final String name;
private final AsyncContext context;
private final Date queued;
public TestWorker(String name, AsyncContext context) {
this.name = name;
this.context = context;
this.queued = new Date(System.currentTimeMillis());
}
@Override
public void run() {
LOG.info(">run: " + name);
/* do some work for 10 sec */
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
ServletResponse response = this.context.getResponse();
response.setContentType("text/plain");
try {
PrintWriter out = response.getWriter();
out.println("Name:\t\t" + this.name);
out.println("Queued:\t\t" + this.queued);
out.println("End:\t\t" + new Date(System.currentTimeMillis()));
out.println("Thread:\t\t" + Thread.currentThread().getId());
out.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.context.complete();
LOG.info("<run: " + name);
}
}
Es posible que desee echar un vistazo a esto: http://stackoverflow.com/questions/ 7749350/illegalstateexception-not-supported-on-asynccontext-startasyncreq-res si desea implementar el procesamiento asincrónico en Tomcat 7. Hay un giro. – JVerstry