Ответ
Использование нестатических и нефинальных полей в сервлете крайне не рекомендуется из-за проблем с потокобезопасностью. Контейнер сервлетов использует один экземпляр сервлета для обработки всех запросов, и несколько потоков могут одновременно читать и изменять такое поле, что приводит к состоянию гонки (race condition) и некорректным данным.
Опасный пример:
public class CounterServlet extends HttpServlet {
private int count; // Нестатическое, нефинальное поле — разделяемое состояние!
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
count++; // Операция не атомарна: чтение-изменение-запись
resp.getWriter().write("Count: " + count);
}
}
Правильные подходы:
- Использовать локальные переменные. Они создаются в стеке каждого потока и безопасны.
-
Использовать потокобезопасные классы из
java.util.concurrent.private final AtomicInteger safeCounter = new AtomicInteger(0); protected void doGet(HttpServletRequest req, HttpServletResponse resp) { int current = safeCounter.incrementAndGet(); // Атомарная операция // ... } - Использовать
ThreadLocalдля хранения состояния, специфичного для потока (например, идентификатор пользовательской сессии). - Использовать синхронизацию (
synchronized) — но это может стать узким местом для производительности. - Объявлять поля как
final, если они неизменяемы и инициализируются при создании сервлета.
Вывод: Состояние сервлета должно быть либо неизменяемым (final), либо управляться через потокобезопасные механизмы, либо избегаться вовсе.