В ответах @Roman и @David Soroko рассказывается, как это сделать в сервлете (как попросил ОП).
Однако этот подход имеет проблему, заключающуюся в том, что tomcat должен выделять поток для каждого запроса, чтобы они могли участвовать в логике очередей / тайм-аутов, реализованной сервлетом. Каждый из этих потоков использует память и другие ресурсы. Это плохо масштабируется. И если вы не сконфигурируете достаточное количество потоков, запросы будут либо отброшены диспетчером запросов tomcat, либо поставлены в очередь / заблокированы по другой логике.
Альтернативный подход заключается в использовании не сервлетной архитектуры в веб-сервере; например Гризли и более конкретно Гризли Комета . Это большая тема, и, честно говоря, я недостаточно знаю об этом, чтобы углубиться в детали реализации.
РЕДАКТИРОВАТЬ - В модели сервлета каждый запрос выделяется одному потоку на весь его срок службы. Например, в типичной модели «проталкивания сервера» каждый активный клиент имеет ожидающий HTTP-запрос, запрашивающий у сервера дополнительные данные. Когда новые данные поступают на сервер, сервер отправляет ответ, и клиент немедленно отправляет новый запрос. В классической модели реализации сервлета это означает, что сервер должен иметь запрос «в процессе» ... и поток ... для каждого активного клиента, даже если большинство потоков просто ожидают поступления данных.
В масштабируемой архитектуре вы бы отсоединили запрос от потока, чтобы поток мог использоваться для обработки другого запроса. Позже (например, когда данные «прибыли» в примере «проталкивания сервера»), запрос будет присоединен к потоку (возможно, другому) для продолжения обработки. В Grizzly я понимаю, что это делается с использованием модели обработки на основе событий, но я думаю, что вы также можете использовать модель на основе сопрограмм.